限制类模板类型

时间:2019-05-23 16:22:03

标签: c++ templates c++17 sfinae

我正在尝试使用SFINAE来限制我正在编写的类的允许模板参数类型。这是我想出的一个简单的人为例子,相信可以说明我想做的事情。

我确定这个问题已经在某个地方得到回答,但是我找不到它。

找到了解决问题的两种方法:

第一(SFINAE):

template <typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type>
class Integer {
public:
    T value;
};

int main() {
    Integer<int> i;             // Alowed
    Integer<double> d;          // Not allowed
    Integer<double, double> dd; // Allowed (Undesired)

    return 0;
}

对于这种解决方案,我不满意的是主函数中的第三个示例可以正常工作。

第二(static_assert):

#include <type_traits>

template <typename T>
class Integer {
    static_assert(std::is_same<T, int>::value, "T must be int");
public:
    T value;
};

int main() {
    Integer<int> i;    // Allowed
    Integer<double> d; // Not allowed

    return 0;
}

我认为这种解决方案很好,但是我想知道是否存在一种更优雅或SFINAE的方法来完成同一件事。

在这种情况下,对于这个简单的示例,我希望能够强制模板类型T必须为整数。当然,在这种情况下,该类甚至不需要成为模板,我可以将Integer类中的类型声明为int类型,但是我想在更复杂的情况下使用在这里学习的内容。

2 个答案:

答案 0 :(得分:4)

您可以通过使用未命名的非类型模板参数来解决第一个示例。更改为

template <typename T, std::enable_if_t<std::is_same_v<T, int>, bool> = true>
class Integer {
public:
    T value;
};

将仅允许Integer<int> i;进行编译。它还可以阻止用户尝试使用Integer<double, true> dd;

进行浏览

答案 1 :(得分:2)

以另一种方式(正确)使用SFINAE:

template <typename T, typename std::enable_if<std::is_same<T, int>::value, int>::type = 0>
class Integer {
public:
    T value;
};

没有劫持。