此代码有效:
// g++ -std=c++11
// (or)
// clang++ -std=c++11
#include <iostream>
template <class T>
struct Tester
{
template <class S = T, class = decltype(S())>
static void Test (int && k)
{
std::cout << "Default constructible" << std::endl;
}
static void Test (...)
{
std::cout << "Not default constructible" << std::endl;
}
};
struct HasDefaultConstructor
{
HasDefaultConstructor() = default;
};
struct NoDefaultConstructor
{
NoDefaultConstructor() = delete;
};
int main ()
{
Tester<HasDefaultConstructor>::Test(int());
Tester<NoDefaultConstructor>::Test(int());
return 0;
}
但是我想了解为什么我需要为间接模板推导S
设置template <class S = T, class = decltype(S())>
。
我更喜欢使用template <class = decltype(T())>
来做,但是在gcc中会导致错误的输出:对Test
方法的所有调用都转到第一个;在clang中会导致错误call to deleted constructor of 'NoDefaultConstructor'
(感谢HolyBlackCat在此处指出clang编译错误)。
为什么?强制我们间接引用类模板的编译器/ c ++标准的过程是什么?
答案 0 :(得分:2)
这是因为您首先实例化了模板类Tester
。因此,需求class = decltype(T())
成为模板类Tester<T>
本身的需求。因此,如果不满意,则模板类格式错误。 编辑:假设ypu确实想编写一个以X
作为模板参数并使用class X = decltype(T())
作为默认条目的模板函数?除了SFINAE的东西,编译器如何告诉它?
间接推论template <class S = T, class = decltype(S())>
将其转换为模板函数Test
的需求,而不是整个类。
这是技术原因。是的,没有人喜欢SFINEA和函数元编程,这就是为什么在C ++ 20中引入概念并开发constexpr编程的原因。