【问题标题】:Why is a particular concept constraint being duplicated in the generated template?为什么在生成的模板中重复了一个特定的概念约束?
【发布时间】:2016-05-21 18:23:12
【问题描述】:

我刚刚开始尝试 C++ 概念,使用 g++ 6.1.0(Debian 软件包版本 6.1.1-1,标志 -std=c++17 -fconcepts),我遇到了以下我不理解的错误消息简化示例:

#include <iterator>
#include <vector>
#include <iostream>

template <typename B>
concept bool ContextualBool = requires(B b) {
  { bool(b) };
  { !b } -> bool;
};

template <typename It>
concept bool InputIterator = requires(const It iconst, const It jconst, It i) {
  typename std::iterator_traits<It>::reference;
  typename std::iterator_traits<It>::value_type;
  { iconst == jconst } -> ContextualBool;
  { iconst != jconst } -> ContextualBool;
  { *i } -> typename std::iterator_traits<It>::reference;
  { ++i } -> It&;
  { *i++ } -> typename std::iterator_traits<It>::value_type;
};

template <typename P, typename Arg>
concept bool Predicate = requires(P pred, Arg x) {
  { pred(x) } -> ContextualBool;
};

template <typename P, typename It>
concept bool InputPredicate = requires {
  typename std::iterator_traits<It>::reference;
  requires Predicate<P, typename std::iterator_traits<It>::reference>;
};

/* Version 1 */
/*
InputIterator{I}
bool all_of(I begin, I end, InputPredicate<I> pred) {
*/
/* Version 2 */
/*
bool all_of(InputIterator begin, InputIterator end,
Predicate<typename std::iterator_traits<InputIterator>::reference> pred) {
*/
/* Version 3 */
bool all_of(InputIterator begin, InputIterator end,
            InputPredicate<InputIterator> pred) {
  while (begin != end) {
    if (!pred(*begin))
      return false;
    ++begin;
  }
  return true;
}

int main() {
  std::vector<int> v { 1, 2, 3, 4, 5 };
  if (all_of(v.begin(), v.end(), [](int n) { return n % 2 == 0; }))
    std::cout << "All elements of v are even\n";
  return 0;
}

在此代码中,版本 1 和版本 2 都成功编译并具有预期的运行时结果。但是,对于版本 3,我收到以下错误消息:

/tmp/concepts_repr.cpp: In function ‘int main()’:
/tmp/concepts_repr.cpp:56:70: error: no matching function for call to ‘all_of(std::vector<int>::iterator, std::vector<int>::iterator, main()::<lambda(int)>)’
       if (all_of(v.begin(), v.end(), [](int n) { return n % 2 == 0; }))
                                                                      ^
/tmp/concepts_repr.cpp:44:10: note: candidate: template<class auto:1, class auto:2, class auto:3, class auto:4>  requires predicate( InputIterator<auto:1>) and predicate(InputPredicate<auto:2, auto:1>) and predicate(InputIterator<auto:3>) and predicate(InputPredicate<auto:4, auto:3>) bool all_of(auto:1, auto:1, auto:4)
     bool all_of(InputIterator begin, InputIterator end,
          ^~~~~~
/tmp/concepts_repr.cpp:44:10: note:   template argument deduction/substitution failed:
/tmp/concepts_repr.cpp:56:70: note:   couldn't deduce template parameter ‘auto:2’
       if (all_of(v.begin(), v.end(), [](int n) { return n % 2 == 0; }))
                                                                      ^

从错误消息看来,由于某种原因,它在生成的模板中生成了 InputIterator 和 InputPredicate 模板参数的重复版本。我不明白为什么会这样,特别是考虑到版本 2 有效。我是否误解了 cppreference.com 的声明:“由等效约束类型说明符引入的所有占位符都具有相同的发明模板参数”?或者这可能是 gcc 中的错误?

【问题讨论】:

    标签: c++ g++ c++-concepts


    【解决方案1】:

    据我所知,概念是对类型名称进行操作,而不是对概念名称概念进行操作。在代码的第 3 版中,我们有 InputPredicate&lt;InputIterator&gt;,但 InputIterator 是概念名称,而不是类型名称。因此编译失败。

    我们真正想要的是InputIterator 概念在beginend 的类型上运行。我们可以通过对函数签名稍作改动来实现这一点:

    bool all_of(InputIterator begin, InputIterator end,
            InputPredicate<decltype(begin)> pred) {
      ...
    }
    

    或者,我们可以显式指定模板参数并使用 requires 子句对其施加约束:

    template<typename It, typename P>
      requires InputIterator<It> && InputPredicate<P, It>
    bool all_of(It begin, It end, P pred) {
      ...
    }
    

    我实际上更喜欢后一种语法,因为我认为它使推导模板参数的预期约束更加清晰。

    【讨论】:

    • InputIterator 出现在InputPredicate&lt;InputIterator&gt; 中时,它被用作占位符,与在beginend 参数的声明中使用时非常相似。它本身不是错误,即使在实例化时也不是。 More placeholder examples.
    • 有趣。是否有将概念描述为占位符的文档?我查看了标准提案,但没有看到与该用例明确相关的任何内容。
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多