PYA*_*PYA 4 c++ sfinae c++11 c++14
#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;
}
Run Code Online (Sandbox Code Playgroud)
我试图为constructor创建的对象(h)调用第二个.我不知道为什么会收到此错误:
Run Code Online (Sandbox Code Playgroud)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是类的模板参数而不是函数的模板参数,因此它不是直接上下文.这意味着它成为一个"硬"错误.这是一个很难的错误,因为无论你发送给构造函数的模板参数的是什么参数,它都将是一个错误.
一个解决方案是添加一个等于的模板参数T,并用它来制作SFINAE:
template <typename... Args, typename U = T, typename = decltype(U{})>
test(Args... args): value(args...)
{
cout <<"ctor running\n";
}
Run Code Online (Sandbox Code Playgroud)
由于U是直接上下文,因此SFINAE适用于此.
使用SFINAE,没有订购.每个匹配函数都是"相等",这意味着如果有多个匹配函数,则没有"更好"的函数,因为它是受约束的.所以用相反的约束来限制另一个是一个好主意:
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";
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
462 次 |
| 最近记录: |