使用gcc替换模板替换和演绎失败

时间:2013-05-31 16:48:56

标签: c++ templates gcc c++11 language-lawyer

我相信我发现了gcc的别名模板处理问题。从本质上讲,当通过引用引用类型时,gcc似乎无法正确地将别名的template-id替换为别名模板实例化。

我能够将一个混乱的现实世界问题简化为C ++ 11标准部分temp.alias(14.5.7 / 2)中提供的非规范示例的微小变化:

#include <vector>

using namespace std;

template <class T>
using Vec = vector<T, allocator<T>>;

template <template <class> class TT>
void f1(TT<int> v);

template <template <class> class TT>
void f2(TT<int>& v);

template <template <class, class> class TT>
void g1(TT<int, allocator<int>> v);

template <template <class, class> class TT>
void g2(TT<int, allocator<int>>& v);

void foo()
{
   Vec<int> v;

   f1(v);    // gcc and clang both correctly yield no matching function error
   g1(v);

   f2(v);    // clang yields a no matching function error
   g2(v);    // gcc yields a no matching function error
}

如上所述,clang 3.3(最近来自svn)和gcc(4.7.2,4.8.0和4.8.1)同意f1 / g1的处理符合标准,但处理方式不同f2 / g2(要清楚,gcc的所有测试版本都接受对f2()的调用,并且在调用g2()时出错。 f1 / g1和f2 / g2之间的差异当然是后一对使用参考参数。

在本例和我的实际问题中,所有指示都是gcc没有正确地将别名模板的实例化类型(例如Vec<int>)转换为别名类型(例如{{1}在尝试推导f2和g2的实例化的模板参数之前。

我的问题是:首先,确实gcc不正确并且在此处更正,第二,是否有任何直接的方式(除了不使用别名模板)以说服gcc拒绝f2并匹配g2。

2 个答案:

答案 0 :(得分:1)

确实这是一个GCC错误。一种解决方法是简单地添加typedef

   typedef Vec<int> vit;
   vit v;

鉴于这是有效的,身份元功能可能也会起作用。

答案 1 :(得分:0)

看起来编译器对推理有问题。明确调用模板可以解决问题 - 我无法说明为什么gcc无法推断以及icpc或clang。

对于icpc(ICC)13.1.0 20130121:

f1<Vec> (v);    // gcc and clang both correctly yield no matching function error
g1(v);
f2<Vec>(v);    // clang yields a no matching function error
g2(v);    // gcc yields a no matching function error

对于gcc(GCC)4.7.2 20121109(Red Hat 4.7.2-8):

f1<Vec> (v);    // gcc and clang both correctly yield no matching function error
g1(v);
f2<Vec>(v);    // clang yields a no matching function error
g2<vector>(v);    // gcc yields a no matching function error