使用enable_if为有符号和无符号变量创建一个可变构造函数

时间:2016-02-01 18:11:17

标签: c++ templates sfinae enable-if

我想使用任何整数类型为类创建构造函数,但要区分有符号和无符号。我不希望它成为类本身的模板。以下不起作用。 Visual Studio只是说没有参数匹配。

class Thing{
public:
    template<typename Integral>
    Thing(
        typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            std::is_signed<Integral>::value
            ,Integral
        >::type num
    ){
        //constructor using signed variable as input
    }
    template<typename Integral>
    Thing(
        typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            !std::is_signed<Integral>::value//notice this is different
            ,Integral
        >::type num
    ){
        //constructor using unsigned variable as input
    }
};

2 个答案:

答案 0 :(得分:6)

我们需要将SFINAE移动到模板中。如果我们使用

class Thing{
public:
    template<typename Integral, typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            std::is_signed<Integral>::value
            ,Integral>::type* = nullptr> // will fail if type does not exist
    Thing(Integral i)
//        ^ use Integral type here
    {
        std::cout << "signed\n";
    }
    template<typename Integral, typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            !std::is_signed<Integral>::value//notice this is different
            ,Integral>::type* = nullptr>
    Thing(Integral i)
    {
        std::cout << "unsigned\n";
    }
};

int main()
{
    int a = 10;
    Thing b(a);
    unsigned int c = 10;
    Thing d(c);
}

我们得到了

signed
unsigned

Live Example

默认情况下,我还必须使构造函数public成为private

答案 1 :(得分:3)

问题是该类型出现在iso8601中,因此编译器无法从std::is_integral<Integral>::value之类的内容中推断出它。试试这个:

#include <iostream>
#include <type_traits>

class Thing{
public:
    template<typename Integral>
    Thing(Integral num,
        typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            std::is_signed<Integral>::value
            ,Integral
        >::type* = nullptr
    ){
        std::cout << "signed\n";
        //constructor using signed variable as input
    }

    template<typename Integral>
    Thing(Integral num,
        typename std::enable_if<
            std::is_integral<Integral>::value &&
            !std::is_same<Integral,bool>::value &&
            !std::is_signed<Integral>::value//notice this is different
            ,Integral
        >::type* = nullptr
    ){
        std::cout << "unsigned\n";
        //constructor using unsigned variable as input
    }
};

int main()
{
    int x{};
    unsigned int y{};
    Thing thing1(x);
    Thing thing2(y);
}

non-deduced context

旁注:构建构造函数public,否则无法实例化对象。