Taylor Huang
Taylor Huang

Reputation: 245

Selectively instantiate member functions of a template with SFINAE

So in a template class, I was trying to instantiate different member according to some information provided statically. In the below template, if some condition holds, the selectiveMember is contained within SelectiveClass, otherwise, the template is intended to be instantiated without selectiveMember but still contain foo.

template<typename T>
struct SelectiveClass{

  void foo(){...}

  template<condition_check<T>::type=0>
  void selectiveMember{...}
}

However, this kind of implementation would discard the whole class if condition is not satisfied. Nevertheless, using the CRTP technique, we can reach the purpose.

template<typename T>
struct SelectiveClass: Specialize<T>{   
  void foo(){...}
}
template<typename T>
struct Specialize{
  template<condition_check<T>::type=0>
  void selectiveMember{...}
}

But with this technique, each selective member would require another specialized inheritance.

So my question is: Is there any more elegant way to allow this kind of selective member template?

Upvotes: 1

Views: 113

Answers (1)

linuxfever
linuxfever

Reputation: 3823

The reason why your enable_if doesn't work the way you want it to, is because it is not used in the immediate context (see, for instance, here). However, if you insert a default template argument in the selectiveMember function, you can achieve what you need. In the example below, I am using a concrete example of a condition but you can replace this with your own.

#include <type_traits>


template<typename T>
struct SelectiveClass{

  void foo(){}

  template <class X = T, std::enable_if_t<std::is_integral<T>::value, X>* = nullptr>
  void selectiveMember(){}
};

using test_int = SelectiveClass<int>;
using test_double = SelectiveClass<double>;

int main() {

    test_int x;
    test_double y;

    x.selectiveMember();
//    y.selectiveMember(); fails to compile as expected
}

Upvotes: 2

Related Questions