Disabling / hiding functions in a template based on compile time constants

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 
+4
source share
2 answers

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 its variant:

 template <size_t n, size_t m> class MyClassT { template <typename EnableIf = char> static MyClassT<n, m> SomeFunc(EnableIf (*)[n == m] = 0) { ... } }; 

more sophisticated alternative (but less surprising if you don't know about SFINAE and pointer to arrays)

 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. Once it becomes more complex, I prefer the partial specialization method.

EDIT: The SFINAE code was incorrect because the template functions were not. Fixed.

+7
source

The ideal way to provide specializations is to use specialized templates. You can move all the base functions to the 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 can add a dummy template template parameter and use enable_if :

 template< typename Dummy = int > typename std::enable_if< M == N, my_class >::type some_func( Dummy* = 0 ); 
+4
source

Source: https://habr.com/ru/post/1379368/


All Articles