为啥在没有 -DPASS 的情况下编译下面的测试用例对 sfinae 不友好

Posted

技术标签:

【中文标题】为啥在没有 -DPASS 的情况下编译下面的测试用例对 sfinae 不友好【英文标题】:why compiling below testcase without -DPASS is not sfinae friendly为什么在没有 -DPASS 的情况下编译下面的测试用例对 sfinae 不友好 【发布时间】:2020-08-08 11:20:46 【问题描述】:
 $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

为什么没有 -DPASS sfinae 在这里不起作用? 我正在努力编译原始测试用例(没有 -DPASS),但我想出了解决方案(-DPASS),但我无法理解其中的区别?

【问题讨论】:

【参考方案1】:

因为与类方法相关的 SFINAE 作用于方法本身的模板参数,而不是包含类的方法。

您可以使用以下技巧绕过此限制“转换”方法参数中的类参数

template <typename T>
struct foo
   
     template <typename U = T,
         typename = /* some test over U */>
     void bar ();

     // ...

这样U是方法bar的模板参数,但与类的模板参数类型相同,T

【讨论】:

简而言之,SFINAE 需要对成员函数/函数本身进行模板化,无论它们属于何处(即类、命名空间等)。 如果类模板参数是完全相同的类型,为什么不能直接在方法的重载解析中使用?

以上是关于为啥在没有 -DPASS 的情况下编译下面的测试用例对 sfinae 不友好的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在vs2010下编写代码的时候代码下面会出现红色波浪线?

为啥在Linux下编写的源程序没有执行权限?每次都要使用chmod +x 呢?

我可以在没有 CURSOR 的情况下编写此查询吗?

在命令提示符下编译 .Net Framework 项目给出 CS0006 而 Visual Studio 中没有错误,为啥?

在不违反 SRP、OCP、DRY 的情况下编写测试

Visual Studio 2015:在没有运行时库的情况下编译 C/C++