部分模板特化问题

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 更专业。