Reputation: 9340
I would like to implement a template class, with specializations for std::is_arithmetic types, as well as other specific vector classes, such as :
struct Vector { double x = 0; double y = 0; double z = 0; };
I have tried:
template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>>>
class arith { static constexpr const T zero() { return (T)0; } };
template<typename T, typename std::enable_if_t<std::is_same_v<typename T, Vector>>>
class arith { static inline Vector zero() { return Vector(); } };
This causes a "template parameter '__formal' is incompatible with the declaration, on second template
I have tried with a generic empty class, that would be specialized:
template<typename T, typename Enable = void>
class arith { };
template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>>>
class arith { static constexpr const T zero() { return (T)0; } };
template<typename T, typename std::enable_if_t<std::is_same_v<typename T, Vector>>>
class arith { static inline Vector zero() { return Vector(); } };
But in that case, both specialization fail to compile with "template parameter 'Enable' is incompatible with declaration"
I also tried full specialization for Vector class, and various other solutions ... without success. I can do it via full specialization for every type, but can't get the std::is_arithmetic version to work.
Upvotes: 1
Views: 478
Reputation: 218343
Before C++20, way to go with a enabler is something like:
template<typename T, typename Enable = void>
class arith;
template<typename T>
class arith<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{
static constexpr const T zero() { return (T)0; }
};
// No need of SFINAE here: fully specialized
template<>
class arith<Vector> { static inline Vector zero() { return Vector(); } };
With C++20, we might use concept
template<typename T>
class arith;
template<typename T>
requires (std::is_arithmetic_v<T>)
class arith<T>
{
static constexpr const T zero() { return (T)0; }
};
// No need of SFINAE here: fully specialized
template<>
class arith<Vector> { static inline Vector zero() { return Vector(); } };
Upvotes: 1
Reputation: 1
The correct syntax for doing this would be as shown below. Note when partially specializing a class template you have not used the template-id.
//------------------vvvv---->this is a non-type parameter
template<typename , auto >
class arith;
template<typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> U>
//---------vvvvv------------------------------------------------------->note this
class arith<T,U> { static constexpr const T zero() { return (T)0; } };
template<typename T, typename std::enable_if_t<std::is_same_v<T, Vector>> U>
//---------vvvvv------------------------------------------------------>note this
class arith<T,U> { static inline Vector zero() { return Vector(); } };
Upvotes: 2