【发布时间】:2018-12-16 09:34:00
【问题描述】:
#include <type_traits>
template<typename T>
struct remove_cvref
{
using type = std::remove_cv_t<
std::remove_reference_t<T>>;
};
template<typename T>
using remove_cvref_t =
typename remove_cvref<T>::type;
template<typename T>
constexpr bool isCc = std::is_copy_constructible_v<
remove_cvref_t<T>>;
class A final
{
public:
A() = default;
template<typename T, bool = isCc<T>> // error
A(T&&) {}
};
A f()
{
A a;
return a;
}
int main()
{}
错误信息:
error : constexpr variable 'isCc<const A &>' must be initialized by a constant expression
1>main.cpp(14): note: in instantiation of variable template specialization 'isCc<const A &>' requested here
1>main.cpp(15): note: in instantiation of default argument for 'A<const A &>' required here
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\type_traits(847): note: while substituting deduced template arguments into function template 'A' [with T = const A &, b1 = (no value)]
1>main.cpp(8): note: in instantiation of variable template specialization 'std::is_copy_constructible_v<A>' requested here
1>main.cpp(14): note: in instantiation of variable template specialization 'isCc<A>' requested here
1>main.cpp(15): note: in instantiation of default argument for 'A<A>' required here
1>main.cpp(21): note: while substituting deduced template arguments into function template 'A' [with T = A, b1 = (no value)]
但是,如果我将类 A 更改如下:
class A final
{
public:
A() = default;
template<typename T,
bool = std::is_copy_constructible_v<
remove_cvref_t<T>>> // ok
A(T&&) {}
};
然后一切正常。
为什么 C++ 的 variable template 没有按预期运行?
【问题讨论】:
-
不确定为什么会出现编译器错误;我正在使用 Visual Studio 2017 CE 版本 15.8.6,我的编译器语言标准设置为
ISO C++ Latest Draft Standard (/std:c++latest),它编译和构建都很好,我什至在 main 内部调用了函数f();,它仍然编译并运行并顺利退出。 -
我的编译器在 windows 上是 clang 7.0
-
可能在编译器如何解释它...
-
IDK 是你故意写这段代码来测试编译器的能力还是有一些你没有注意到的事实:你模板
A(T&&)是一个复制构造函数,它需要参与确定T obj(std::declval<Args>()...);在std::is_copy_constructible中的格式是否正确。换句话说,std::is_copy_constructible依赖于它自己。所以实际上会出现一些奇怪的行为。至于为什么第二种方法似乎“有效”,那可能是一些 SIFAE 的东西打破了循环依赖,并丢弃了这个模板。 -
见这里:wandbox.org/permlink/T6E5GveUuBNVQbCZ,即使
::value成员在std::is_copy_constructible中也消失了
标签: c++ templates c++17 template-meta-programming typetraits