typedef名称与可变模板参数名称一致时出现GCC错误
GCC error when typedef name coincides with variadic template parameter name
我偶然发现了typedef
和我想了解的可变模板参数之间的一个奇怪交互。以下代码使用clang编译,但使用GCC时出现错误:
template<typename T> // no error if this is not a template
struct Traits;
#pragma GCC diagnostic ignored "-Wunused-parameter"
template<typename ...args>
void function(args... e) {}
template<typename T>
struct Caller {
typedef typename Traits<T>::types traits_types; // no error if this is changed to a 'using' directive
template<typename ...types> // no error if the pack is converted to a single parameter
static void method(types... e) {
function<traits_types>(e...);
}
};
GCC行为
当我用GCC编译(而不是链接(它时,我在第14行得到一个错误:
$ g++-9.2.0 -Wall -Wpedantic -Wextra -std=c++11 -c test.cpp
test.cpp: In static member function ‘static void Caller<T>::method(types ...)’:
test.cpp:14:31: error: parameter packs not expanded with ‘...’:
14 | function<traits_types>(e...);
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
test.cpp:14:31: note: ‘types’
$
它的作用就好像GCC首先替代了traits_types
的定义,这将产生
template<typename ...types>
static void method(types... e) {
function<typename Traits<T>::types>(e...);
}
然后评估模板参数替换,此时它将令牌types
的最后一次出现视为未扩展的参数包并相应地产生错误。
我已经用GCC 6.4.0、7.3.0、8.2.0、8.3.0、9.1.0和9.2.0以及几个旧版本进行了测试,所有版本的行为都是一致的。
叮当声
然而,当我用clang编译这个时,它工作得很好。
$ clang++-8 -Wall -Wpedantic -Wextra -std=c++11 -c test.cpp
$
这似乎是因为它首先替换了参数包types
和,然后处理名称traits_types
。
我在clang 6.0.0、7.0.1和8.0.1以及一些旧版本中一直看到这种行为。
问题
在标准C++11中,GCC给出错误是否正确,或者代码是否有效?还是未定义/实现定义/未指定?
我浏览了cppreference.com关于模板和typedef的大部分内容,但没有找到任何明确解决此问题的内容。我还检查了其他几个问题(1、2、3、4、5等(,据我所知,所有这些问题看起来都很相似,但并不完全适用于这种情况。
如果这实际上是一个编译器错误,那么在错误跟踪器中找到一个相关问题的链接,确认GCC(或clang,如果适用(没有正确处理这个问题,就会很好地解决这个问题。
是的,这是一个错误。您观察到的"就好像GCC首先替代了traits_types的定义">,然后是GCC错误90189:的表现
来源:
struct A { using CommonName = char; }; template <typename T, typename... CommonName> struct B { using V = typename T::CommonName; }; template struct B<A>; Output: <source>:7:37: error: parameter packs not expanded with '...': 7 | using V = typename T::CommonName; | ^ <source>:7:37: note: 'CommonName' Compiler returned: 1
被所有GCC版本拒绝。接受clang,msvc。
GCC的行为就像您直接编写typename Traits<T>::types
一样,然后它会被与模板参数包的名称相同的依赖名称types
所混淆。您可以通过给包一个不同的名称来绕过它,但在标准C++中,依赖名称可以与包的名称相同。因为一个必须是合格的,而另一个是不合格的,所以不应该有歧义。
- 在分配和发布递增循环迭代器时C++无限循环(gcc 错误?
- GCC 警告和 gcc 错误消息之间的区别
- 调试模板时出现问题.专门针对 Linux GCC 7、GCC 6、GCC 5、GCC 4.9 错误构建失败:模板参数 1
- typedef名称与可变模板参数名称一致时出现GCC错误
- 条件变量:wait_for.gcc错误
- 不可复制类数据成员的统一初始化导致gcc错误
- 在类中将不完整类型的unique_ptr初始化为 nullptr 时编译 gcc 错误
- GCC-7:错误:无法识别的命令行选项"-M64"
- C++ GCC 错误:"sqrtl"不是"std"的成员
- 在联盟中,不愿命名的未命名结构的成员是错误或GCC错误
- 尾随返回类型中带有 SFINAE 的 GCC 错误
- 与lambda一起使用虚拟继承在初始化列表中捕获此问题的GCC错误
- 通过指向成员的指针对嵌套访问进行编译时评估期间出现 GCC 错误
- 从成员变量访问静态 constexpr 成员,GCC 错误?
- std::seed_seq编译错误(GCC错误?)
- GCC 错误:如果已知函数正常返回,则函数可能是属性"pure"的候选者
- iostream GCC错误,转换为boost::filesystem::iostream for Windows
- GCC错误?链式方法,断开序列点
- 是否存在GCC错误:默认std :: function
- GCC 错误错误的 ELF 类:ELFCLASS64,尽管有 -m64 标志