当我尝试使用以下元函数检索元组的第一种类型时,可以使用 GCC 编译代码,但不能使用 Clang。关于这个小片段,我有两个问题。
- 这是合法的 C++ 代码吗?为什么?或者为什么不呢?
- 是否有适用于两种编译器的解决方法(或正确的替代方法)?
#include <tuple>
template<typename>
struct first_type;
template<template<typename, typename...> typename T, typename T1, typename... Ts>
struct first_type<T<T1, Ts...>>
{ using type = T1; };
template<typename T>
using first_type_t = typename first_type<T>::type;
using tuple_type1 = first_type_t<std::tuple<int, int, double>>;
应要求,Clang生成的错误信息:
<source>:12:1: error: implicit instantiation of undefined template
'first_type<std::tuple<int, int, double>>'
using first_type_t = typename first_type<T>::type;
^
<source>:14:21: note: in instantiation of template type alias
'first_type_t' requested here
using tuple_type1 = first_type_t<std::tuple<int, int, double>>;
^
<source>:4:8: note: template is declared here
struct first_type;
^
总结:
- 由 IWonderWhatThisAPIDoes 回答;要完全避免编译器差异,只需放弃模板化模板参数至少具有单一类型的要求。
- 正如 Nathan Oliver 所指出的;如果你需要元组的第一种类型(或者任何给定索引的类型),只需使用 std::tuple_element元函数代替。
- 正如 HolyBlackCat 所指出的;似乎 Clang 对模板化模板参数执行的裁决比标准的技术要求更严格。可以通过传递
-frelaxed-template-template-args
编译器标志来禁用此行为。
最佳答案
暂时将您的结构声明更改为(从而摆脱不完整的类型):
template<typename>
struct first_type {};
将您遇到的错误更改为:
no type named 'type' in 'first_type<std::tuple<int, int, double>>'
这给了我们有值(value)的信息:编译器选择了模板的通用版本,这意味着 Clang 不认为元组是有效的 template<typename,typename...>class
实例化 first_type
with (这是真的 - template<typename,typename...>class
接受一个或多个参数,而元组也可以为空)。正如评论中所指出的,这对标准本身并不重要,但是 Clang rejects it on purpose .
一个元组是一个template<typename...>class
, 所以...
template<template<typename...> typename T, typename T1, typename... Ts>
struct first_type<T<T1, Ts...>> {
using type = T1;
};
关于c++ - 编译器与简单元函数的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67691007/