g++错误与部分模板专业化
g++ Bug with Partial Template Specialization
我正在为g++(4.8.1_1版本,Macports)和clang++(3.3版本,Macport)编写一些TMP繁重的代码。当g++用UNBRIDLED FURY拒绝下面的代码列表时,clang++用grace和精彩编译它。
- 哪个同谋是对的?(我强烈怀疑这是g++,但在提交错误报告之前,我想从其他人那里得到一些保证。)
- 你有什么简单或优雅的解决方案可以建议吗?(我需要使用模板别名,所以切换到structs(这会导致g++接受代码)不是一个选项。)
这是代码列表,仅为您制作。
template <class... Ts>
struct sequence;
template <int T>
struct integer;
// This definition of `extents` causes g++ to issue a compile-time error.
template <int... Ts>
using extents = sequence<integer<Ts>...>;
// However, this definition works without any problems.
// template <int... Ts>
// struct extents;
template <int A, int B, class Current>
struct foo;
template <int A, int B, int... Ts>
struct foo<A, B, extents<Ts...>>
{
using type = int;
};
template <int B, int... Ts>
struct foo<B, B, extents<Ts...>>
{
using type = int;
};
int main()
{
using t = foo<1, 1, extents<>>::type;
return 0;
}
这是g++的输出:
er.cpp: In function 'int main()':
er.cpp:39:41: error: ambiguous class template instantiation for 'struct foo<1, 1, sequence<> >'
using t = typename foo<1, 1, extents<>>::type;
^
er.cpp:26:8: error: candidates are: struct foo<A, B, sequence<integer<Ts>...> >
struct foo<A, B, extents<Ts...>>
^
er.cpp:32:8: error: struct foo<B, B, sequence<integer<Ts>...> >
struct foo<B, B, extents<Ts...>>
^
er.cpp:39:43: error: 'type' in 'struct foo<1, 1, sequence<> >' does not name a type
using t = typename foo<1, 1, extents<>>::type;
^
这是clang++的输出:
谢谢你的帮助!
这看起来像是一个g++错误,因为显然foo<B, B, extents>
比foo<A, B, extents>
更专业(后者可以匹配前者匹配的任何内容,但不能反之亦然),所以编译器应该选择该专业化。
正如您自己所指出的,将extents
从模板别名更改为类模板解决了这个问题。
如果我正确理解,问题可以归结为确定以下模板专业化中的一个是否比另一个更专业:
template <int A, int B, class Current>
struct foo;
template <int A, int B, int... Ts>
struct foo<A, B, extents<Ts...>>
{
using type = int;
};
template <int B, int... Ts>
struct foo<B, B, extents<Ts...>>
{
using type = int;
};
答案是是,对于第二个专业化中允许的任何参数组合,通过使模板参数A == B
,第一个专业化允许相同的组合。另一方面,A != B
不能与第二个专门化匹配的第一个模板专门化的任何实例化,因此第二个严格地比第一个更专门化。
我相信g++可能是正确的。线路
using t = foo<1, 1, extents<>>::type
是在非推导上下文中使用模板参数,因此它不能使用为模板参数给定的实际值来解决歧义,只能使用它们的类型,这是不够的。
C++标准第14.8.2.5节第4段规定:
在大多数情况下,用于组成p的类型、模板和非类型值参与模板参数推导。也就是说,它们可以用于确定模板参数的值,并且这样确定的值必须与其他地方确定的值一致。然而,在某些上下文中,该值不参与类型推导,而是使用模板参数的值要么是在其他地方推导出来的,要么是明确规定的。如果模板参数仅在非推导上下文中使用,并且没有明确指定,则模板参数推导失败。
未推导的上下文为:
x使用限定id 指定的类型的嵌套名称说明符
第14.8.2.4节第11段规定:
在大多数情况下,所有模板参数都必须有值才能成功推导,但出于部分排序的目的,模板参数可以保留为没有值,前提是它不用于用于部分排序的类型。[注:在非推导上下文中使用的模板参数被视为已使用。--尾注]
因此,我们处于非推导上下文中,这意味着所有模板参数都必须有值。因此,如果区段<>如果没有确定类型,那么根据标准,结果将是模糊的。看似合理的
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- 如何使用默认参数等选择模板专业化
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 为什么在班级专业化上会出现错误?
- 类模板的编译错误,但其专业化除外
- C 概念和模板专业化;如何获得用户友好的编译器错误
- 错误:类模板部分专业化包含无法推导的模板参数
- 功能指针数组(包括成员功能)投掷模板专业化错误
- 实例化错误后成员函数模板的专业化,以及成员函数的顺序
- 实例化错误后如何避免专业化
- Singleton模板专业化编译的奇怪错误
- g++错误与部分模板专业化
- 为什么未使用的部分专业化没有错误
- 带有外部错误的模板专业化
- 为什么模板专业化中的显式实例化会给我带来错误