【问题标题】:C++ constructor SFINAEC++ 构造函数 SFINAE
【发布时间】:2018-06-04 18:21:03
【问题描述】:
#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 正在运行”

我在这里缺少什么?第一个constructor 呼叫应该是SFINAed,因为typename = decltype(T()) 不能工作,因为t 不能是default constructed,而是我得到一个ambiguous 呼叫错误。

【问题讨论】:

    标签: c++ c++11 c++14 sfinae


    【解决方案1】:

    SFINAE 仅在直接上下文中发生。由于T 是类的模板参数而不是函数的模板参数,因此它不是直接上下文。这意味着它成为一个“硬”错误。这是一个硬错误,因为无论您向构造函数的模板参数发送什么参数,它始终是一个错误。

    一种解决方案是添加一个等于T 的模板参数,并使用它来制作SFINAE:

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

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

    Live example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多