Search code examples
c++c++11templatessfinae

why compiling below testcase without -DPASS is not sfinae friendly


 $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?


Solution

  • 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.