模板等价或模板功能等价?

时间:2017-12-06 16:18:05

标签: c++ templates

在C ++标准[temp.over.link]中,解释了函数模板等价的确定不应涉及英雄的努力"编译器。

作为一个例子,C ++标准提出了这个:

// guaranteed to be the same
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+10>);
// guaranteed to be different
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+11>);
// ill-formed, no diagnostic required
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+1+2+3+4>);

此规则是否也适用于涉及元编程的案例,如下例所示?

template<class T>
struct t_{
   using type = T;
   };
//ill-formed or different?
template<class T> T f(T);
template<class T> typename t_<T>::type f(T);

2 个答案:

答案 0 :(得分:3)

让我们从简单的案例开始:

template <typename T> using id = T;

template<class T> T f(T);
template<class T> id<T> f(T);

根据the relevant rule,这对我来说显然是不正确的,无需诊断。这两个声明在功能上是等效的,但不是简单地重命名模板参数的方式(并且没有要考虑的任何从属名称)。

案件更复杂:

template <typename T> struct id_t { using type = T; };
template <typename T> using id = typename id_t<T>::type;

template<class T> T f(T);
template<class T> id<T> f(T);

我认为这可能形成错误,因为它们在功能上并不相同。可能存在id_t的特化,这两个声明实际上是不同的 - 所以这些实际上是不同的声明。

答案 1 :(得分:2)

我认为在这种情况下,他们被认为是不同的:

template<class T>
struct t_{
   using type = T;
   };
//ill-formed or different?
template<class T> T f(T);
template<class T> typename t_<T>::type f(T);

因为[temp.over.link]说(强调我的

  

确定是否两个   依赖名称是等价的,只考虑名称本身,而不是名称查找的结果   模板的上下文

由于Ttypename t_<T>::type命名不同,编译器将接受这些模板声明。

现在,您无法实际调用其中任何一个,因为生成的模板实例化功能相同,从而导致歧义。这种程序形式错误,无需诊断*(见@Barry's great answer)。

MSVC 19.00.23506clang 6.0.0gcc 8.0.0似乎都同意我的意见(没有人发出诊断信息)。

请注意,编译器允许声明这些模板,只要它们不被调用,而这样的东西即使没有实例化模板也不会编译:

template<class U> typename t_<U>::type f(U){return {};}
template<class T> typename t_<T>::type f(T){return {};}

*&#34;如果程序包含函数声明 功能相同但不相同的模板,程序格式错误,无法诊断 。需要&#34;

相关问题