template <typename T>
class A
{
template <std::enable_if_t<std::is_signed_v<T>, bool> = true>
constexpr value_type determinant()
{
}
}
I wanna determinant function is instantiated only when type T is signed type
so I try this codes, but when type T is unsigned compiler still try instantiate determinant function.
I don't wanna specialize template function about each signed type T.
I want to use std::is_signed_v type traits to simplify codes
With SFINAE you can enable/disable a method of a class when the condition tested is related to a template parameter of the method itself. Doesn't works testing a template parameter of the class.
You can solve the problem passing through a method template parameter that is defaulted with the type of the class/struct template parameter.
For example
#include <iostream>
#include <type_traits>
template <typename T>
struct foo
{
template <typename U = T,
std::enable_if_t<std::is_signed_v<U>, bool> = true>
constexpr std::size_t bar ()
{ return sizeof(T); }
};
int main()
{
foo<signed int> fs;
foo<unsigned int> fu;
fs.bar(); // compile
//fu.bar(); // compilation error
}
The problem of this solution is that you can "hijack" it explicating a template parameter
fu.bar(); // compilation error
fu.bar<int>(); // compile
To avoid the hijacking risk, you can (other solutions are possible but this is my preferred) add a non-type variadic template parameter before U
// .......VVVVVVVV add this to avoid the hijacking problem
template <int ...,
typename U = T,
std::enable_if_t<std::is_signed_v<U>, bool> = true>
constexpr std::size_t bar ()
{ return sizeof(T); }
// ...
fu.bar(); // compilation error
fu.bar<int>(); // compilation error
fu.bar<1, 2, 3, int>(); // compilation error
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With