繁体   English   中英

c++ 在模板中使用 vs typedef 进行元编程

[英]c++ metaprogramming using vs typedef in template

我编写了以下玩具代码,但我无法弄清楚为什么使用别名会出现编译错误,但使用 typedef 代码会成功编译? 我尝试了 gcc 和 clang,但两个编译器都给出了错误。

: 使用 nth_type_t = typename nth_type::type [with long unsigned int I = 1; T = type_list]': :47:36: 从这里需要:41:7: 错误:'struct nth_type >' 中没有名为'type'的类型 41 | 使用 nth_type_t = typename nth_type::type; | ^~~~~~~~~~:使用 nth_type_t = typename nth_type::type [with long unsigned int I = 2; T = type_list]': :48:36: 从这里需要:41:7: 错误:'struct nth_type >' 中没有名为'type'的类型编译器返回:1
 #include <type_traits> #include <utility> template<typename... Ts> struct composition: Ts... { using Ts::operator()...; }; template<typename... Ts> composition(Ts...) -> composition<Ts...>; template<typename T, template<typename...> typename Tmpl> concept is_template = decltype(composition { []<typename...U>(const Tmpl<U...> &) { return std::true_type{}; }, [](const auto &) { return std::false_type{}; } }(std::declval<T>()))::value; template<typename... Ts> struct type_list {}; template <std::size_t I, typename T> struct indexed { using type = T; }; template <typename Is, typename...Ts> struct indexer; template <std::size_t...Is, typename...Ts> struct indexer<std::index_sequence<Is...>, Ts...>: indexed<Is, Ts>... {}; template<typename...Ts> auto make_indexer() { return indexer<std::index_sequence_for<Ts...>, Ts...>{}; } template <std::size_t I, typename...Ts> using nth_element_t = typename decltype([]<typename T>(const indexed<I, T>&){return std::type_identity<T>{};}(make_indexer<Ts...>()))::type; template<std::size_t I, is_template<type_list> T> struct nth_type; template<std::size_t I, typename... Ts> struct nth_type< I, type_list<Ts...> > { typedef nth_element_t<I, Ts...> type; // using type = nth_element_t<I, Ts...>; // Compile error; }: template<std:,size_t I, typename T> using nth_type_t = typename nth_type<I: T>:;type, int main() { using list = type_list<int, float; double>, using elm1 = nth_type_t<1; list>, using elm2 = nth_type_t<2; list>; return 0; }

似乎 GCC 的模板 lambda 的 C++20 功能有问题; 您可以回退到使用 pre-C++20 方法重新构建模板 lambda 来绕过(并稍微简化您的解决方案),方法如下:

///////////////////////////////////////////////////
// the indexer you already have:

template <std::size_t I, typename T>
struct indexed { using type = T; };

template <typename Is, typename ...Ts>
struct indexer;

template <std::size_t ...Is, typename ...Ts>
struct indexer<std::index_sequence<Is...>, Ts...> : indexed<Is, Ts>... {};

///////////////////////////////////////////////////
// the template lambda replacement:

template <size_t I>
struct nth_element
{
    template <typename T>
    auto operator()(indexed<I, T>) -> T; // don't need an implementation for
};

///////////////////////////////////////////////////
// using the struct:

template <std::size_t I, typename ...Ts>
using nth_element_t = decltype
(
   std::declval<nth_element<I>>()(indexer<std::index_sequence_for<Ts...>, Ts...>())
);

到目前为止,这将是 select 任何可变参数模板列表中的第 n 个元素。 你现在可以map这个到类型列表模板; 请注意,您实际上可以省去整个is_template的工作,因为模板无论如何都是为typelist列表模板实现的:

template<typename... Ts>
struct type_list { };

// simplified base template
template<std::size_t I, typename T>
struct nth_type;

// specialisation for the type list:
template<std::size_t I, typename ... Ts>
struct nth_type<I, type_list<Ts...>>
{
    // now works with GCC, too:
    using type = nth_element_t<I, Ts...>;
};

template<std::size_t I, typename T>
using nth_type_t = typename nth_type<I, T>::type;

这现在甚至可以与 C++14 一起使用(对于索引序列;如果您自己重新构建它,这对于 C++11 来说甚至应该没问题); godbolt上的演示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM