1

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?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Taylor Huang
  • 245
  • 2
  • 8
  • You are asking for an elegant way to provide a functionality for some `T` only. Have you considered using a non-member function? In general, preferring free functions over dozens of member functions can also help to improve encapsulation etc. Some IMHO good arguments are presented in the talk [Free Your Functions](https://www.youtube.com/watch?v=WLDT1lDOsb4) by Klaus Iglberger. – Julius Jun 14 '18 at 21:09
  • @Julius I was using this technique to provide interface. How would you implement this with only free functions? Could you elaborate the idea? – Taylor Huang Jun 15 '18 at 05:49
  • The free function can look like this: `template void selectiveNonMember(SelectiveClass& self) { /* extend the functionality of SelectiveClass by using its member functions as building blocks */ }`. – Julius Jun 15 '18 at 12:07
  • could you provide an example of the `condition_check` please? – linuxfever Jun 22 '18 at 16:19
  • @linuxfever something like `enable_if::value,int>` – Taylor Huang Jul 08 '18 at 10:14

1 Answers1

2

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
}
linuxfever
  • 3,763
  • 2
  • 19
  • 43