Is it possible to conditionally hide or disable functions in a template class using compile time constants?
Imagine the following class:
template<size_t M, size_t N>
class MyClassT
{
// I only want this function available if M == N, otherwise it is illegal to call
static MyClassT<M, N> SomeFunc()
{
...
}
}
MyClassT<2,2>::SomeFunc(); // Fine
MyClassT<3,2>::SomeFunc(); // Shouldn't even compile
Use partial specialization, and inheritance:
// Factor common code in a base class
template <size_t n, size_t m>
class MyClassTBase
{
// Put here the methods which must appear
// in MyClassT independantly of n, m
};
// General case: no extra methods
template <size_t n, size_t m>
class MyClassT : MyClassTBase<n, m>
{};
// Special case: one extra method (you can add more here)
template <size_t n>
class MyClassT<n, n> : MyClassTBase<n, n>
{
static MyClassT<n, n> SomeFunc()
{
...
}
};
Another option is to use SFINAE: std::enable_if
or a variant thereof:
template <size_t n, size_t m>
class MyClassT
{
template <typename EnableIf = char>
static MyClassT<n, m> SomeFunc(EnableIf (*)[n == m] = 0)
{
...
}
};
the more verbose alternative (but less surprising if you don't know about SFINAE and pointer to arrays) being
template <size_t n, size_t m>
class MyClassT
{
template <typename Dummy = char>
static MyClassT<n, m>
SomeFunc(typename std::enable_if<n == m, Dummy>::type * = 0)
{
...
}
};
Generally, I prefer SFINAE approaches where there is one or two member functions to enable or disable. As soon as it gets more complex than this, I prefer the partial specialization technique.
EDIT: The SFINAE code was wrong, since there were not template functions. Corrected.
The ideal way to provide specializations is to use template specializations. You can move all the basic functionality to a base class:
template< size_t M, size_t N >
class basic_class{ ... };
template< size_t M, size_t N >
class my_class : basic_class< M, N > { ... };
template< size_t M >
class my_class< M, M > : basic_class< M, N > { ... };
Alternatively, you could add a dummy template parameter and use enable_if
:
template< typename Dummy = int >
typename std::enable_if< M == N, my_class >::type some_func( Dummy* = 0 );
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