【发布时间】:2013-05-31 16:48:55
【问题描述】:
我相信我发现 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。
【问题讨论】:
-
@DyP 感谢您的链接,但不幸的是,这有点不同 - 那里没有扣除。在我的问题中,问题是别名模板的替换点相对于扣除点的时间,可以这么说。 f1 需要被标准拒绝,因为 v 的类型确实是
vector<int, allocator<int>>,无法匹配单参数模板模板参数。 -
哦,对不起,我一定跳过了那个.. [temp.alias]/2 "注意:别名模板名称永远不会被推断出来。"
-
您在中间段落中提到的
Vec<int>和vector<int, allocator<int>>需要反引号。 (HTML 解析正在去掉尖括号之间的东西,因为它没有被代码引用。)我试图为你把它们放进去,但看起来我的编辑被拒绝了。 -
GCC 4.8.1 在您发布此内容前 5 小时发布 :) 这看起来像是 GCC 中的一个错误,请向gcc.gnu.org/bugzilla 报告 - 谢谢!
-
您好,我添加了语言律师标签以帮助吸引那些倾向于知道这些问题的答案的人。
标签: c++ templates gcc c++11 language-lawyer