$cat test.cc
#include <type_traits>
struct foo{
};
template<typename F,typename A>
struct other
{
template<typename f, typename a,
#ifndef PASS
typename = decltype(std::declval<F>()(std::declval<A>()))>
#else
typename = decltype(std::declval<f>()(std::declval<a>()))>
#endif
static std::true_type _Fn(int);
template<typename...>
static std::false_type _Fn(...);
typedef decltype(_Fn<F,A>(0)) type;
};
int main() {
static_assert(std::is_same<std::false_type,other<foo&,int>::type>::value,"PASSED");
return 0;
}
Compilation command:
g++ test.cc -std=c++11
why without -DPASS sfinae does not work here? I was struggling to compile the original test case (without -DPASS) but I came up with the solution (-DPASS) but I can not understand the difference?
Because SFINAE, related to class methods, works over template parameters of the methods itself, not over methods of the containing class.
You can go around this limitation "transforming" a class parameter in a method parameter with the following trick
template <typename T>
struct foo
{
template <typename U = T,
typename = /* some test over U */>
void bar ();
// ...
This way U
is a template parameter of the method bar
but with the same type of the template parameter of the class, T
.