【问题标题】:Limiting Class Template Types限制类模板类型
【发布时间】:2019-05-23 16:22:02
【问题描述】:

我正在尝试使用 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;
}

我不喜欢这个解决方案的是 main 函数中的第三个示例有效。

第二个(静态断言):

#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 类型,但我想在更复杂的情况下使用我在这里学到的东西。

【问题讨论】:

  • C++20中会有concepts
  • 我发现static_assert 解决方案很好:如果您的班级的用户尝试使用Integer&lt;float&gt;,他们会得到一个很好的编译错误,而不是丑陋的 sfinae 相关的文本墙。跨度>

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


【解决方案1】:

您可以通过使用未命名的非类型模板参数来修复您的第一个示例。改成

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

只允许Integer&lt;int&gt; i; 编译。它还阻止用户尝试使用 Integer&lt;double, true&gt; dd; 绕过它

【讨论】:

    【解决方案2】:

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

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

    不再劫持。

    【讨论】:

    • 这里是不是有太多右尖括号了?我不确定哪一个是多余的。
    • @Pavis11:错字已修复。
    • 您在 C++17 问题中获得了 C++11!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    相关资源
    最近更新 更多