C++:`enable_if` 限制支持特定算术运算的类型

C++: `enable_if` to restrict types that support specific arithmetic operations

我想定义只能应用于支持乘法的类型的模板函数,例如intlongfloat 以及带有重载运算符的自定义类型,例如 Martix:

class Matrix {
    public:
        Matrix operator*(const Matrix& other) const;
}

是否可以通过这种方式限制模板类型?

template <typename T, typename = std::enable_if_t< /* multiplication is defined */ >>
T power (T base, unsigned int exponent) {
    // ...
}

如果只需要测试,如果一个类型可以自相乘,可以使用:

template <class T, 
          class = decltype(std::declval<T>() * std::declval<T>())>
T power (T base, unsigned int exponent) {
     ...
}

查看 fundamentals TS v2 中的 is_detected(还提供了可能的实现)。如果您想对各种操作进行频繁检查,这为您提供了良好的基础。它基本上允许您检查给定类型上是否可以进行指定操作。

首先,您定义操作类型:

template <typename Lhs, typename Rhs>
using multiplication_t = decltype(std::declval<Lhs>() * std::declval<Rhs>());

然后你从中创建一个类型特征:

template <typename Lhs, typename Rhs>
constexpr bool can_multiply = is_detected<multiplication_t, Lhs, Rhs>::value;

您现在可以使用特征作为 enabled_if 的条件:

template <typename T, typename = std::enable_if_t<can_multiply<T, unsigned int>>
T power (T base, unsigned int exponent) {
    // ...
}

这也增加了一些可读性(至少在我看来),因为 can_multiply 清楚地表达了您的意图。

Here 是一个完整的实施示例。

Another 包含更多操作的示例。