考虑以下简单的代码:
template<typename ...types>
class myclass
{
using payload_type = mylib::type_traits::type_or_tuple_t<types...>;
template<typename... T>
std::pair<bool, std::optional<payload_type>> try_push(T &&...data)
{
payload_type t;
std::optional<decltype(t)> o;
// this FAILS.
//std::optional<payload_type> res;
return {true, std::move(o)};
}
};
上面,type_or_tuple
助手简单地将可变参数包转换为以下类型:如果可变参数包是单一类型,则转换为单一类型;如果可变参数包是多种类型,T
则转换为类型元组( )。tuple<types...>
Gcc (9/10/11) 无法编译此代码。具体来说,它似乎无法正确扩展payload_type
上面的代码,这当然是通过帮助程序获取的类型type_or_tuple
:
g++-11 -O2 -std=c++17 -pedantic wtf.cpp -Wall -Wextra -D_POSIX_SOURCE=200809L -lrt -lmylib -lstdc++ -o q
wtf.cpp:27:70: error: parameter packs not expanded with ‘...’:
27 | std::pair<bool, std::optional<payload_type>> try_push(T &&...data)
| ^
wtf.cpp:27:70: note: ‘T’
另请注意:
payload_type t;
std::optional<decltype(t)> o;
可以编译。但是注释掉的那一行不能。
另一方面,clang
编译这个没有任何问题。
这是 gcc 中的错误还是语言使用不正确?有什么想法可以调整它以使其编译吗?
这是一个最小可重现的示例,其中包括的定义is_type_or_tuple
:
#include <iostream>
#include <type_traits>
#include<optional>
#include <tuple>
using namespace std;
template<typename... types>
struct type_or_tuple {
using tup = std::tuple<types...>;
using T = std::conditional_t<(std::tuple_size_v<tup> == 1),
std::tuple_element_t<0, tup>,
tup>;
using is_tuple = std::conditional_t<(std::tuple_size_v<tup> > 1),
std::true_type,
std::false_type>;
};
template<typename... types>
using type_or_tuple_t = typename type_or_tuple<types...>::T;
//
template<typename ...types>
class myclass
{
using payload_type = type_or_tuple_t<types...>;
template<typename... T>
std::pair<bool, std::optional<payload_type>> try_push(T &&...data)
{
payload_type t;
std::optional<decltype(t)> o;
// WILL NOT COMPILE!
//std::optional<payload_type> res;
return {true, std::move(o)};
}
};
int main(int, const char **){
myclass<unsigned> c;
}
3
最佳答案
1
这是一个错误。gcc 会混淆T
成员函数模板中的 和T
类型特征中的 。只需将 特征简单地更改为使用不同的名称而不是T
,例如type
,gcc 也会感到高兴:
template <class... types>
struct type_or_tuple {
using tup = std::tuple<types...>;
using type = std::conditional_t<sizeof...(types) == 1,
std::tuple_element_t<0, tup>, tup>;
};
template <class... types>
using type_or_tuple_t = typename type_or_tuple<types...>::type;
和新的
|
type_or_tuple
定义。最好扩展您的问题以包含–
type_or_tuple
。–
–
|