Reputation: 45434
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
Reputation: 35803
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
Better. Don't use this. Please.
Upvotes: 1
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