Include class member based on template

I already know that you can enable (or not) a class method using std::enable_if

for example:

 template<size_t D, size_t E> class Field { ... size_t offset(const std::array<float,D>& p) const { ... } template<typename TT = size_t> typename std::enable_if<D!=E, TT>::type offset(const std::array<float,E>& p) const { return offset(_projection(p)); } ... }; 

This helps not to call a function that is not valid in a particular case, and also eliminates overload errors ... which is very nice for me!

I would like to go further and make some of my class members present only if they are needed. Thus, I get an error if I try to use an object that would not otherwise be triggered.

I tried to do

 template<size_t D, size_t E> class Field { ... template<typename TT = projectionFunc> typename std::enable_if<D!=E, TT>::type _projection; } 

But the compiler tells me:

 erreur: data member '_projection' cannot be a member template 

Is there any way to achieve what I want?

+6
source share
2 answers

Keep the data elements in a separate class, which you can then specialize as needed.

 template<size_t D, size_t E> class Field { template<size_t, size_t> struct Field_Members { int _projection; }; template<size_t V> struct Field_Members<V, V> { }; Field_Members<D, E> m; }; 

and then use m._projection , etc.

Field_Members need not be a nested class template; You can move it outside if necessary. It is also possible to inherit Field from it, but then it will be a dependent base, and you will have to write this->_projection , so it does not save a lot of input.

+5
source

AFAIK, this is not possible with a simple SFINAE inside a class template. Of course, you can have a member type depending on the compile-time condition, i.e. Via std::conditional , but not completely excluding it.

What you can do, of course, use a different class template, for example

 template<bool Condition, typename T> struct Has { T value; }; template<typename T> struct Has<false,T> {}; 

and declare a member (or base) of this type and access the object through Has<>::value :

 typename<Condition> class foo { Has<Condition, double> x; // use x.value (only if Condition==true) }; 
+4
source

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


All Articles