C++ 在函数模板的声明部分中定义时,对任意类型属性的函数重载失败

C++ 在函数模板的声明部分中定义时,对任意类型属性的函数重载失败,c++,templates,C++,Templates,我发现了一篇关于这个主题的好文章,在第10页,作者指出了两件重要的事情: 当使用启用码重载函数模板时,启用码将放置在声明部分 不需要实现通常的dispatcher—一个单独的接口函数,用于向实现进行分派 第1点。就这样可以找到。作者声明(打印出的文章的第10页)也可以使用enablers作为函数参数,这就是我要做的,但是ADL在该示例中失败了 第2点。依赖SFINAE并减少功能模板集。当启用码失败时,SFINAE将不会报告错误,参数的扣除将导致选择最适合的模板 说完这些,我修改了之前的: #包括

我发现了一篇关于这个主题的好文章,在第10页,作者指出了两件重要的事情:

  • 当使用启用码重载函数模板时,启用码将放置在声明部分
  • 不需要实现通常的dispatcher—一个单独的接口函数,用于向实现进行分派 第1点。就这样可以找到。作者声明(打印出的文章的第10页)也可以使用enablers作为函数参数,这就是我要做的,但是ADL在该示例中失败了

    第2点。依赖SFINAE并减少功能模板集。当启用码失败时,SFINAE将不会报告错误,参数的扣除将导致选择最适合的模板

    说完这些,我修改了之前的:

    #包括
    #包括
    模板
    结构标记{};
    结构Atag{};
    结构Btag{};
    模板
    已启用结构标记
    {
    静态常量布尔值=标准::是否相同
    <
    typename标记::type,
    标签
    >::价值;
    typedef typename std::如果
    <
    std::是一样的吗
    <
    typename标记::type,
    标签
    >::价值,
    类型
    >::类型类型;
    };
    模板
    typename std::启用\u如果
    <
    已启用标记::值&&
    标记_已启用::值,
    A.
    >::类型
    工人(
    康斯特食宿酒店
    )
    {
    结果,;
    
    std::coutSFINAE在模板参数替换期间工作(在推导函数模板的类型或类模板的专门化时)

    另一方面,你已经在类定义中加入了逻辑。那太晚了。只有在模板被实例化并且参数类型已经推导出来之后,才会检查它,然后它会触发一个硬错误

    只需去掉
    typedef
    内部的
    tag\u enabled
    。您不需要它,只需要
    value
    成员传递到
    enable\u if
    (这就是应该发生替换失败的地方-
    enable\u if
    将根据其第一个参数的值具有或不具有嵌套的typedef)

    #include <type_traits>
    #include <iostream>
    
    template<typename Type>
    struct tag {}; 
    
    struct Atag {}; 
    struct Btag {};
    
    template<typename Type, typename Tag>
    struct tag_enabled
    {
        static const bool value = std::is_same
        <
            typename tag<Type>::type, 
            Tag 
        >::value;
    
        typedef typename std::enable_if
        <
            std::is_same
            <
                typename tag<Type>::type, 
                Tag 
            >::value,
            Type
        >::type type; 
    };
    
    template<typename A, typename B>
    typename std::enable_if
    <
        tag_enabled<A, Atag>::value && 
        tag_enabled<B, Btag>::value, 
        A
    >::type
    worker(
        B const & b
    )
    {
        A result; 
    
        std::cout << "Btag -> Atag" << std::endl;
    
        return result; 
    }
    
    template<typename A, typename B>
    typename std::enable_if
    <
        tag_enabled<A, Atag>::value && 
        tag_enabled<B, Atag>::value, 
        A
    >::type
    worker(
       B const & b 
    )
    {
        A result; 
    
        std::cout << "Atag -> Atag" << std::endl;
    
        return result; 
    }
    
    struct test_a {}; 
    struct test_b {}; 
    
    template<>
    struct tag<test_a>
    {
        typedef Atag type; 
    };
    
    template<>
    struct tag<test_b>
    {
        typedef Btag type;
    };
    
    int main()
    {
        test_a ta1; 
        test_b tb1; 
    
        auto ta2 = worker<test_a>(ta1); 
        auto ta3 = worker<test_a>(tb1);
    
        return 0;
    }
    
       tag_enabled<A, Atag>::value && // Check if A is tagged with Atag
       tag_enabled<B, Btag>::value, // Check if B is tagged with Btag
       A
    
    test-template.cpp: In instantiation of ‘struct tag_enabled<test_a, Btag>’:
    test-template.cpp:33:33:   required by substitution of ‘template<class A, class B> typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Btag>::value), A>::type worker(const B&) [with A = test_a; B = test_a]’
    test-template.cpp:86:34:   required from here
    test-template.cpp:27:13: error: no type named ‘type’ in ‘struct std::enable_if<false, test_a>’
         >::type type; 
                 ^
    test-template.cpp: In instantiation of ‘struct tag_enabled<test_b, Atag>’:
    test-template.cpp:51:33:   required by substitution of ‘template<class A, class B> typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Atag>::value), A>::type worker(const B&) [with A = test_a; B = test_b]’
    test-template.cpp:87:34:   required from here
    test-template.cpp:27:13: error: no type named ‘type’ in ‘struct std::enable_if<false, test_b>’
    
    typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Atag>::value), A>::type worker(const B&) [with A = test_a; B = test_b]