【发布时间】:2017-11-05 12:11:29
【问题描述】:
我正在阅读cppreference page on Constraints 并注意到这个例子:
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
我很困惑他们为什么使用std::forward。一些尝试在模板参数中支持引用类型?难道我们不想用左值调用swap,当T 和U 是标量(非引用)类型时,forward 表达式不是右值吗?
例如,考虑到他们的Swappable 实现,我预计这个程序会失败:
#include <utility>
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
class MyType {};
void swap(MyType&, MyType&) {}
void f(Swappable& x) {}
int main()
{
MyType x;
f(x);
}
不幸的是,g++ 7.1.0 给了我一个internal compiler error,这并没有说明这一点。
这里T 和U 都应该是MyType,std::forward<T>(t) 应该返回MyType&&,它不能传递给我的swap 函数。
Swappable 的这个实现是错误的吗?我错过了什么吗?
【问题讨论】:
-
Concepts 真的要成为 c++1z 的一部分吗?
-
不,不是。我太乐观了:)
-
顺便说一句,内部错误似乎是由使用
Swappable作为模板约束引起的。如果用作要求,GCC 似乎能够正确处理它。或者更具体地说,void f(Swappable& x) {}和template<Swappable S> void f(S& x) {}都会导致内部错误,但template<typename S> void f(S& x) requires Swappable<S> {}会编译(并发出错误,因为std::forward确实使它寻找右值引用版本)。 -
It seems to have that problem with any concept that takes two template parameters, with the second defaulting to the first (i.e., any concept with
template<typename T, typename U = T>).在实际使用中遇到概念,在扩展概念的同时似乎无法正确推导参数,需要使用requires语法(这样一来参数在遇到概念之前已经推导出来,允许它从中推导出另一个)。 -
这是 n4382 中的一个错字,已修复为使用转发参考
标签: c++ c++-concepts c++20