在构造函数中提升enable_if

时间:2012-08-24 20:05:52

标签: c++ boost enable-if

我有一个模板化的类,我想只在类型为double时启用某个构造函数。这段代码出了什么问题?

template<typename T>
class B: public A<T>
{
public:
    B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0);
}

int main(int argc,char *argv[])
{
B<double> B( 6, 6 );
}

我收到错误:“类型'boost :: enable_if_c'参数的默认参数类型为'int'”,但我不确定这是什么意思。

提前非常感谢你。

3 个答案:

答案 0 :(得分:7)

嗯,你真的不能那样做。如果你提供的某些T不是double,那么编译器将尝试解析enable_if_c<false>::type,这将失败,使整个类实例化失败,而不仅仅是构造函数。

您可以使用C ++ 11的默认函数模板参数来实现相同的功能。

下面的代码使用您在代码中使用的boost功能的C ++ 11版本来实现:

#include <type_traits>

template<typename T>
class B {
public:
    // T == double -> this ctor can be used
    template<typename U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type>
    B(int arg1, double arg2) {}

    // Default ctor, available to every class.
    B() {}
};

int main(int argc,char *argv[])
{
    B<double> b_double( 6, 6 );
    B<int> b_int;

    // This line fails
    //B<int> b_fails(6, 6);
}

答案 1 :(得分:2)

在这种情况下你不能使用SFIANE,因为它仅在替换 function 模板参数flails时才有效,而不是在 class 模板参数的替换失败时。

您需要的是专业化

但据我了解,您应该在double案例中复制常见案例的实现,但只添加新的构造函数。

在这种情况下,我建议我使用一些有线技术:您可以从专业化的常见案例中获得。

然后你面临两个问题:

  1. 您仍然应该double专门的常见案例来推导
  2. 你不应该调用常见的默认构造函数,而是一些专门的。
  3. 我们走了:

    template<typename T, bool = false>
    class B
    {
    public:
        B() { std::cout << "B common\n"; }
        void yahoo() { std::cout << "yahoo!\n"; }
    
    protected:
        struct internal_t;
        B(internal_t*){}
    
    };
    
    template <>
    struct B<double, false>: public B<double, true>
    {
        B(int, int):B<double, true>(0) { std::cout << "B double\n"; }
    };
    
    int main(int argc,char *argv[])
    {
        B<int> ib;
        B<double> b(2,5);
    
        ib.yahoo();
        b.yahoo();
    }
    

答案 2 :(得分:0)

B(int arg1=0, typename boost::enable_if_c<boost::is_same<T, double>::value>=0);

您忘记了boost::enable_if_c指定类型的第二个参数,忘记了::type,而忘记了参数名称。

如果您想要B(int arg1=0, int arg2=0)行,请使用

B(int arg1=0,
  typename boost::enable_if_c<boost::is_same<T, double>::value, int>::type arg2=0);

更好的是,不要使用下划线c版本的enable if。只需使用enable if:

B(int arg1=0,
  typename boost::enable_if<boost::is_same<T, double>, int>::type arg2=0);