C++构造函数SFINAE
C++ constructor SFINAE
#include <iostream>
using namespace std;
template <typename T>
class test {
public:
T value;
template <typename... Args, typename = decltype(T())>
test(Args... args): value(args...)
{
cout <<"ctor running\n";
}
template <typename... Args>
test(Args...) : value(1)
{
cout <<"ctor unspec running\n";
}
};
class t
{
public:
t() = delete;
explicit t(int) {}
};
int main()
{
test<t> h;
}
我正在尝试为创建的对象 (h
) 调用第二个 constructor
。我不知道为什么会出现此错误:
prog.cc: In function 'int main()':
prog.cc:45:13: error: call of overloaded 'test()' is ambiguous
test<t> h;
^
prog.cc:25:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; T = t]'
test(Args... args)
^~~~
prog.cc:19:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; <template-parameter-2-2> = t; T = t]'
test(Args... args): value(args...)
^~~~
我试图制作整个 class t
private
但这也没有解决它。我想要第二个 constructor
到 运行 即打印 `
"ctor unspec running"
我在这里错过了什么?第一个 constructor
调用应该是 SFINAed
,因为 typename = decltype(T())
不会工作,因为 t
不能是 default constructed
但我得到一个 ambiguous
调用错误.
SFINAE 仅在直接上下文中发生。由于 T
是 class 的模板参数而不是函数的模板参数,因此它不是直接上下文。这意味着它变成了 "hard" 错误。这是一个硬错误,因为无论您向构造函数的模板参数发送什么参数,它始终是一个错误。
一个解决方案是添加一个等于 T
的模板参数,并用它来制作 SFINAE:
template <typename... Args, typename U = T, typename = decltype(U{})>
test(Args... args): value(args...)
{
cout <<"ctor running\n";
}
由于U
是直接上下文,这里应用SFINAE。
使用 SFINAE,没有完成排序。每一个匹配函数都是"equal",也就是说如果有多个匹配函数,就没有"better"一个,因为被约束了。所以用相反的约束来约束另一个是个好主意:
template <typename... Args, typename U = T,
std::enable_if_t<!std::is_default_constructible<U>::value>* = nullptr>
test(Args...) : value(1)
{
cout <<"ctor unspec running\n";
}
#include <iostream>
using namespace std;
template <typename T>
class test {
public:
T value;
template <typename... Args, typename = decltype(T())>
test(Args... args): value(args...)
{
cout <<"ctor running\n";
}
template <typename... Args>
test(Args...) : value(1)
{
cout <<"ctor unspec running\n";
}
};
class t
{
public:
t() = delete;
explicit t(int) {}
};
int main()
{
test<t> h;
}
我正在尝试为创建的对象 (h
) 调用第二个 constructor
。我不知道为什么会出现此错误:
prog.cc: In function 'int main()': prog.cc:45:13: error: call of overloaded 'test()' is ambiguous test<t> h; ^ prog.cc:25:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; T = t]' test(Args... args) ^~~~ prog.cc:19:5: note: candidate: 'test<T>::test(Args ...) [with Args = {}; <template-parameter-2-2> = t; T = t]' test(Args... args): value(args...) ^~~~
我试图制作整个 class t
private
但这也没有解决它。我想要第二个 constructor
到 运行 即打印 `
"ctor unspec running"
我在这里错过了什么?第一个 constructor
调用应该是 SFINAed
,因为 typename = decltype(T())
不会工作,因为 t
不能是 default constructed
但我得到一个 ambiguous
调用错误.
SFINAE 仅在直接上下文中发生。由于 T
是 class 的模板参数而不是函数的模板参数,因此它不是直接上下文。这意味着它变成了 "hard" 错误。这是一个硬错误,因为无论您向构造函数的模板参数发送什么参数,它始终是一个错误。
一个解决方案是添加一个等于 T
的模板参数,并用它来制作 SFINAE:
template <typename... Args, typename U = T, typename = decltype(U{})>
test(Args... args): value(args...)
{
cout <<"ctor running\n";
}
由于U
是直接上下文,这里应用SFINAE。
使用 SFINAE,没有完成排序。每一个匹配函数都是"equal",也就是说如果有多个匹配函数,就没有"better"一个,因为被约束了。所以用相反的约束来约束另一个是个好主意:
template <typename... Args, typename U = T,
std::enable_if_t<!std::is_default_constructible<U>::value>* = nullptr>
test(Args...) : value(1)
{
cout <<"ctor unspec running\n";
}