我相信我发现 gcc 的别名模板处理存在问题。本质上,当通过引用引用类型时,gcc 似乎无法正确地将别名的模板 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>
)转换为别名类型(例如) vector<int, allocator<int>>
f2 和 g2。
我的问题是:首先,这里确实 gcc 不正确和 clang 正确,其次,是否有任何直接的方法(除了不使用别名模板)来说服 gcc 拒绝 f2 并匹配 g2。