Edit: The short answer to my question is that I had a mistaken view of what SFINAE can do and it does not check the function body at all: does sfinae instantiates a function body?
I have an issue similar to this one: Is it possible to write a template to check for a function's existence?
The difference is that I want to not only check if the function exists, but I also want to know if it will actually pass SFINAE. Here is an example of what I'm trying to accomplish:
struct A
{
void FuncA() { std::cout << "A::FuncA" << std::endl; }
};
struct B
{
void FuncA() { std::cout << "B::FuncA" << std::endl; }
void FuncB() { std::cout << "B::FuncB" << std::endl; }
};
template<typename T>
struct Inter
{
void FuncA() { t.FuncA(); }
void FuncB() { t.FuncB(); }
T t;
};
// Always takes some sort of Inter<T>.
template<typename InterType>
struct Final
{
void CallFuncs()
{
// if( t.FuncA() exists and can be called )
t.FuncA();
// if( t.FuncB() exists and can be called )
t.FuncB();
}
InterType t;
};
void DoEverything()
{
Final<Inter<A>> finalA;
Final<Inter<B>> finalB;
finalA.CallFuncs();
finalB.CallFuncs();
}
Note that in CallFuncs(), both FuncA() and FuncB() will always exist, but they may not compile depending on the type T used in Inter. When I tried to use the answer in the above linked question it seemed to always give me true which I'm guessing is because it's only checking that the function exists, not that it can actually be compiled (though I can't rule out that I didn't screw something up...)
In order to conditionally call the functions I figure I can use enable_if as such:
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
i.FuncA();
}
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
i.FuncB();
}
template<typename InterType>
struct Final
{
void CallFuncs()
{
TryCallFuncA(t);
TryCallFuncB(t);
}
InterType t;
};
but I'm not sure if there's any way I can get a boolean value to pass into enable_if. Is there any way I can accomplish this or do I need to fall back to some sort of manually maintained type traits that indicate whether the functions exist?
For what it's worth as far as the available C++11 feature set, I'm using MSVC 2010.
edit: To add an important note, in my actual situation the implementation of the class Inter is effectively opaque at the point where I need to determine whether or not Inter::FuncA/FuncB will compile so I can't just bubble up the child types and check for the existence of the function on them.