C++ 在函数模板的声明部分中定义时,对任意类型属性的函数重载失败
我发现了一篇关于这个主题的好文章,在第10页,作者指出了两件重要的事情:C++ 在函数模板的声明部分中定义时,对任意类型属性的函数重载失败,c++,templates,C++,Templates,我发现了一篇关于这个主题的好文章,在第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]