Walter
Walter

Reputation: 45434

compile-time conditional member function call in C++

I have a template class for which certain member functions only make sense if the template parameters satisfy certain conditions. Using, for instance, std::enable_if<> I can define them only for these cases, but how can I call them conditionally? Here is a brief example

template<class T> class A
{
   typename std::enable_if<std::is_floating_point<T>::value>::type a_member();
   void another_member()
   {
     a_member(); // how to restrict this to allowed cases only?
   }
};

Upvotes: 1

Views: 4659

Answers (2)

Linuxios
Linuxios

Reputation: 35803

WARNING: This is a complete, terrible hack that I have not tried that may never work.

Try adding this to the class declaration:

typename std::enable_if<std::is_floating_point<T>, int*>::type a_enabled_p() { return 0;};
void another()
{
  if((a_enabled_p()+1)==1)
  {
    //Not enabled
  }
  else if((a_enabled_p()+1)==sizeof(int))
  {
    //Is enabled
  }
}

Here's why this horror might work. If they are floating point, the return value of the predicate is an int*. If they are, there is no typedef, and it defaults to int (I hope). When you add 1 to an int*, you are really adding sizeof(int). Adding 1 to an int increments by one. That means that by checking the value of adding one, we know.

Note: Don't use this. It was fun to come up with, but the above answer is MUCH, MUCH

MUCH

Better. Don't use this. Please.

Upvotes: 1

JoeG
JoeG

Reputation: 13192

Firstly, you can't use SFINAE like that - the template type parameter needs to be on the function, not the class.

A full solution looks like this:

template<class T> class A
{
private:
   template <class S>
   typename std::enable_if<std::is_floating_point<S>::value>::type a_member() {
       std::cout << "Doing something";
   }

   template <class S>
   typename std::enable_if<!std::is_floating_point<S>::value>::type a_member() {
       //doing nothing
   }

public:
   void another_member()
   {
     a_member<T>();
   }
};


int main() {
    A<int> AInt;
    AInt.another_member();//doesn't print anything

    A<float> AFloat;
    AFloat.another_member();//prints "Doing something"
}

Upvotes: 9

Related Questions