我相信我发现了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。
答案 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