2

I would like to define template function that can be applied only to types that support multiplication, e.g. int, long, float, and custom types with overloaded operators like Martix:

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

Is it possible to restrict template type in this way?

template <typename T, typename = std::enable_if_t< /* multiplication is defined */ >>
T power (T base, unsigned int exponent) {
    // ...
}
Vitaly Isaev
  • 5,392
  • 6
  • 45
  • 64
  • Possible duplicate of [Check if a class has a member function of a given signature](https://stackoverflow.com/questions/87372/check-if-a-class-has-a-member-function-of-a-given-signature) – Acorn Jun 03 '19 at 21:44
  • That won't work for int, float, and double – Alecto Irene Perez Jun 03 '19 at 21:58

2 Answers2

6

If you only need to test, if a type can be multiplied by itself, you can use:

template <class T, 
          class = decltype(std::declval<T>() * std::declval<T>())>
T power (T base, unsigned int exponent) {
     ...
}
stena
  • 667
  • 5
  • 19
3

Take a look at is_detected from fundamentals TS v2 (there is also a possible implementation provided). This provides you with a good base in case you want to do frequent checks on various operations. It basically allows you to check if a specified operation is possible on the given types.

First, you define your operation type:

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

then you make a type trait out of it:

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

You can now use the trait as a condition for enabled_if:

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

This also adds some readability (imo at least), cause can_multiply clearly expresses your intention.

Here is a full implementation as example.

Another example with more operations.

Timo
  • 9,269
  • 2
  • 28
  • 58