45

如何编写只接受数字类型(、、、等)作为模板的intdouble模板float

4

2 回答 2

63

您可以使用std::is_arithmetic类型特征。如果您只想启用具有此类类型的类的实例化,请将其与以下内容结合使用std::enable_if

#include <type_traits>

template<
    typename T, //real type
    typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type
> struct S{};

int main() {
   S<int> s; //compiles
   S<char*> s; //doesn't compile
}

对于enable_if更易于使用的版本,以及免费添加的disable_if,我强烈建议您阅读这篇关于此事的精彩文章

在 C++ 中,上述技术有一个名为“替换失败不是错误”的名称(大多数使用首字母缩写词 SFINAE)。您可以在wikipediacppreference.com上阅读有关此 C++ 技术的更多信息。

从 C++20 开始,概念使这变得更容易并且不会破坏界面:

#include <concepts>

template<typename T>
concept arithmetic = std::integral<T> or std::floating_point<T>;

template<typename T>
  requires arithmetic<T>
struct S{};
// Shorthand: template<arithmetic T> struct S {};

请注意,有许多用户类型也意味着在算术上使用,因此在通用接口中更可取的是涵盖您正在寻找的操作而不是您正在寻找的类型的更一般的概念。

于 2013-01-12T14:29:39.163 回答
25

我发现从该template<typename T, typename = ...>方法收到的错误消息非常神秘(VS 2015),但发现static_assert具有相同类型特征的 a 也可以工作,并让我指定错误消息:

#include <type_traits>

template <typename NumericType>
struct S
{
    static_assert(std::is_arithmetic<NumericType>::value, "NumericType must be numeric");
};

template <typename NumericType>
NumericType add_one(NumericType n)
{
    static_assert(std::is_arithmetic<NumericType>::value, "NumericType must be numeric");
    return n + 1;
}

int main()
{
    S<int> i;
    S<char*> s; //doesn't compile

    add_one(1.f);
    add_one("hi there"); //doesn't compile
}
于 2016-05-10T18:05:50.380 回答