【问题标题】:How do I do proper SFINAE on inheriting constructors?如何在继承构造函数上做正确的 SFINAE?
【发布时间】:2014-11-09 23:35:51
【问题描述】:

我正在尝试在构造函数上执行 SFINAE。我想为整数启用一个重载,为其他所有内容启用一个重载。我知道我可以创建一个 base(int)base(T) 构造函数,但我想这样做。

template <class T>
struct base
{
    template <class T1 = T>
    base(T1, typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr) {}

    template <class T1 = T>
    base(T1, typename std::enable_if<!std::is_same<T1, int>::value>::type* = nullptr) {}
};

然后我创建一个主要的Base 类来继承构造函数:

template <class T>
struct Base : base<T>
{
    using base<T>::base;
};

但是当我用任何T 实例化Base 时,我得到了这些错误:

source_file.cpp:21:15: error: call to deleted constructor of 'Base<int>'
    Base<int> v(4);
              ^ ~
source_file.cpp:16:25: note: deleted constructor was inherited here
    using base<T>::base;
                        ^
source_file.cpp:7:5: note: constructor cannot be inherited
    base(T1, typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr) {}
    ^

当我直接实例化base 时,它可以正常工作。为什么我在做SFINAE的时候不能继承构造函数?如果没有第二个构造函数重载,一切正常。

【问题讨论】:

标签: c++ c++11


【解决方案1】:

您可以在示例程序中完全避免这个问题,只需在base 中定义泛型构造函数并为base&lt;int&gt; (DEMO) 提供特化:

template <class T>
struct base
{
    base(T) { std::cout << "generic constructor\n"; }
};

template <>
base<int>::base(int) { std::cout << "int specialization\n"; }

或使用标签调度代替 SFINAE (DEMO):

template <class T>
class base
{
    base(std::true_type, int) { std::cout << "int specialization\n"; }
    base(std::false_type, T) { std::cout << "generic constructor\n"; }

public:
    base(T t) : base(std::is_same<int, T>{}, std::move(t)) {}
};

【讨论】:

    【解决方案2】:

    与构造函数的参数列表不同,整个模板 参数列表总是被继承,包括默认模板参数。把 SFINAE 放在那里:

    template <class T>
    struct base
    {
        template <class T1 = T,
          typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr>
        base(T1) {}
    
        template <class T1 = T,
          typename std::enable_if<!std::is_same<T1, int>::value>::type* = nullptr>
        base(T1) {}
    };
    

    这适用于 Clang 和 GCC,在 -std=c++11-std=c++1z 模式下。 (仅测试最新版本,分别为 3.6 和 5.1。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2013-06-01
      • 2023-04-03
      相关资源
      最近更新 更多