Wal*_*ter 5 c++ templates partial-specialization template-specialization c++11
我有以下类结构
// file foo.h:
struct foo_base
{ ... }
template<typename T> struct foo : foo_base
{ ... };
template<typename F>
using is_foo = std::is_convertible<F,foo_base>;
template<typename, typename=void> struct aux;
template<typename Foo>
struct aux<Foo, typename std::enable_if<is_foo<Foo>::value>::type>
{ ... }; // specialisation for any foo
Run Code Online (Sandbox Code Playgroud)
// file bar.h:
#include "foo.h"
template<typename T> struct bar : foo<T>
{ ... };
template<typename T>
struct aux<bar<T>>
{ ... }; // specialisation for bar<T>
Run Code Online (Sandbox Code Playgroud)
现在,问题在于提供的aux<bar<T>>两种专业aux都是可行的.有没有办法避免这种歧义而不为每个人提供另一种专业化T?请注意,对文件的修改foo.h不得知道文件bar.h.
注意应解决歧义,以便bar.h选择文件中提供的专业化aux<bar<T>>.最初,bar不是模板,专业化aux<bar>不是部分的,因此是首选的.通过制作bar模板产生了问题.
小智 4
编译器认为没有struct aux<bar<T>>比第二个模板参数更专业的了struct aux<Foo, typename std::enable_if<is_foo<Foo>::value>::type>。您可以在您的专业化中以相同的方式指定第二个参数bar<T>:
template<typename T>
struct aux<bar<T>, typename std::enable_if<is_foo<bar<T>>::value>::type>
{ };
Run Code Online (Sandbox Code Playgroud)
部分模板特化的规则很复杂,但我会尝试非常简单地解释:
三个(你的两个,加上我的一个)相关专业是
template<typename Foo>
struct aux<Foo, typename std::enable_if<is_foo<Foo>::value>::type>
template<typename T>
struct aux<bar<T>> // or aux<bar<T>, void>
{ };
template<typename T>
struct aux<bar<T>, typename std::enable_if<is_foo<bar<T>>::value>::type>
{ };
Run Code Online (Sandbox Code Playgroud)
根据标准 (14.5.5.2),为了确定哪个类模板部分特化是最专业的,需要回答的问题是以下哪个函数模板重载将是调用中的最佳匹配f(aux<bar<T>>()):
template<typename Foo>
void f(aux<Foo, typename std::enable_if<is_foo<Foo>::value>::type>); // 1
template<typename T>
void f(aux<bar<T>>); // or aux<bar<T>, void> // 2
template<typename T>
void f(aux<bar<T>, typename std::enable_if<is_foo<bar<T>>::value>::type>); // 3
Run Code Online (Sandbox Code Playgroud)
反过来,函数的偏序规则表明 1 并不比 2 更专业,并且 2 也不比 1 更专业,粗略地说,因为 1 并不明显比 2更专业,而 2 也不明显比 2 更专业。比 1 更专业。“显然更专业”并不是标准说法,但这本质上意味着基于其中一个的类型参数,另一个的类型参数是不可推导的。
然而,当比较 1 和 3 时,1 的参数可以从 3 推出:Foo可以推出为bar<T>。因此,3 至少与 1 一样特化。但是,3 的参数不能从 1 推导出来:T根本无法推导出来。因此,编译器的结论是 3 比 1 更专业。