Dav*_*ard 6 c++ stdvector c++-concepts c++20
我正在尝试 C++20 概念,但遇到了一个无法解释的奇怪问题。
\n我正在尝试定义一个concept检查给定迭代器是否可以递增(很好)的方法,并且还检查类型是否因此而改变(不好)。
原谅我的无知,我错过了什么?错误的最后一行指出:
\n\' 注意:\xe2\x80\x98++ it\xe2\x80\x99 不满足返回类型要求\n{ ++it } -> std::same_as; \'
\n#include <functional>\n#include <vector>\n\ntemplate<typename Iter>\nconcept Iterable = requires(Iter it){\n { ++it } // Check iterator can be incremented (compiles but does not check return type)\n { ++it } -> std::same_as<Iter>; // Also check the return type (**fails**)\n};\n\ntemplate<typename Iter>\nrequires Iterable<Iter>\nvoid doesNothing(Iter current, Iter end){\n while(current != end){\n ++current;\n }\n};\n\nint main(){\n std::vector<int> v = {1, 2, 3};\n doesNothing(v.begin(), v.end());\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n预先非常感谢您。
\n我期待这一行:
\n#include <functional>\n#include <vector>\n\ntemplate<typename Iter>\nconcept Iterable = requires(Iter it){\n { ++it } // Check iterator can be incremented (compiles but does not check return type)\n { ++it } -> std::same_as<Iter>; // Also check the return type (**fails**)\n};\n\ntemplate<typename Iter>\nrequires Iterable<Iter>\nvoid doesNothing(Iter current, Iter end){\n while(current != end){\n ++current;\n }\n};\n\nint main(){\n std::vector<int> v = {1, 2, 3};\n doesNothing(v.begin(), v.end());\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n将“管道”返回{++it}到模板中,std::same_as<T, U>结果是std::same_as<std::vector<int>::iterator, std::vector<int>::iterator>当然会被接受。
编辑:巴里的出色回答与此相关: Why does decltype(auto) return a reference here?
\nBar*_*rry 13
我期待这一行:
Run Code Online (Sandbox Code Playgroud){ ++it } -> std::same_as<Iter>;将返回“管道”
{++it}到模板中std::same_as<T, U>,结果std::same_as<std::vector<int>::iterator, std::vector<int>::iterator>当然会被接受。
你说对了一半。
的含义{ ++it } -> std::same_as<Iter>是我们正在检查这++it是一个有效的表达式并且std::same_as<decltype((++it)), Iter>成立,这是正确的。
但decltype((+it))事实并非如此Iter。它是Iter&。这就是你的检查失败的原因。
这就是为什么std::weakly_incrementable指定为:
template<class I>
concept weakly_incrementable =
movable<I> &&
requires(I i) {
typename iter_difference_t<I>;
requires is-signed-integer-like<iter_difference_t<I>>;
{ ++i } -> same_as<I&>; // not required to be equality-preserving
i++; // not required to be equality-preserving
};
Run Code Online (Sandbox Code Playgroud)