简体   繁体   English

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;
}

I am trying to call the second constructor for the object created ( h ). 我试图为创建的对象调用第二个constructorh )。 I do not know why I get this error: 我不知道为什么会收到此错误:

 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...) ^~~~ 

I tried to make the entire class t private but that did not fix it either. 我试图将整个class t设为private但也没有修复它。 I want the second constructor to run ie print ` 我想要第二个constructor运行即打印`

"ctor unspec running" “ctor unspec running”

What am I missing here? 我在这里错过了什么? The first constructor call should be SFINAed away since typename = decltype(T()) wont work as t can not be default constructed but instead I get an ambiguous call error. 第一个constructor调用应该是SFINAed远,因为typename = decltype(T())不会工作,因为t不能default constructed ,而是我得到一个ambiguous调用错误。

SFINAE only happen with immediate context. SFINAE只发生在紧急情况下。 Since T is a template argument of the class and not the template argument of the function, it is not immediate context. 由于T是类的模板参数而不是函数的模板参数,因此它不是直接上下文。 That means it becomes an "hard" error. 这意味着它成为一个“硬”错误。 It's an hard error because no matter what argument you send to the template argument of the constuctor, it will always be an error. 这是一个很难的错误,因为无论你发送给构造函数的模板参数的是什么参数,它总是会出错。

A solution would be to add a template argument equal to T , and use it to make SFINAE: 一个解决方案是添加一个等于T的模板参数,并用它来制作SFINAE:

template <typename... Args, typename U = T, typename = decltype(U{})>
test(Args... args): value(args...)
{
   cout <<"ctor running\n";
}

Since U is immediate context, SFINAE is applied here. 由于U是直接上下文,因此在此处应用SFINAE。

With SFINAE, there is no ordering done. 使用SFINAE,没有订购。 Every matching function is "equal", which means that if there is multiple matching function, there is no "better" one because it is constrained. 每个匹配函数都是“相等”,这意味着如果有多个匹配函数,则没有“更好”的函数,因为它是受约束的。 So it would be a good idea to constrain the other one with a contrary constraint: 所以用相反的约束来限制另一个是一个好主意:

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";
}

Live example 实例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM