【发布时间】:2021-05-25 15:23:30
【问题描述】:
当我尝试使用以下元函数来检索元组的第一种类型时,可以使用 GCC 编译代码,但不能使用 Clang。关于小sn-p,我有两个问题。
- 这是合法的 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编译器标志来禁用此行为。
【问题讨论】:
-
当有差异时,一般clang是对的,MSVS是错的,GCC会编译你扔给它的任何东西。
-
FWIW,你可以使用
std::tuple_element代替using first_type_t = typename std::tuple_element<0, T>::type; -
@NathanOliver 谢谢,我完全忽略了这一点:D
-
template<typename T1, typename... Ts>class T中的名称没有用处,并且在重复使用后有点误导。 -
感谢您的参与,贾罗德。感谢您的建议,我已经相应地更新了最初的问题。