stdlib 是否提供类型列表?

Does the stdlib provide a type list?

提问人:sbi 提问时间:6/16/2019 最后编辑:sbi 更新时间:9/12/2019 访问量:706

问:

在现代 C++ 中,标准库是否提供类型列表模板?

int main() {
    using int_types = type_list<int,long,short,char>;
    std::cout << length<int_types>::value << ' '
              << typeid(element<2,int_types>::type).name();
}

请注意,它不存储任何值(就像存储一样)。它只是一个类型列表。int_typesstd::tuple

模板元编程 C++标准库

评论

1赞 StoryTeller - Unslander Monica 6/16/2019
大概不会做,因为对象是在某个时候创建的?你的评论暗示了这一点,只是想澄清这一点。std::tupleint_types
1赞 paxdiablo 6/16/2019
简短的回答:不,长的回答:还没有:-)也许如果您指出了您想做什么(而不是如何做),我们可以提供更多帮助。换句话说,你到底想实现什么?
1赞 interjay 6/16/2019
为什么不使用你永远不需要实例化的呢? 并允许您在编译时查询类型列表。std::tupletuple_sizetuple_element
1赞 sbi 6/17/2019
@interjay:因为有时(例如,在选择重载函数时),我可能不得不实例化它。

答:

2赞 Aykhan Hagverdili 6/16/2019 #1

使用 type,但不要实例化它:std::tuple

#include <iostream>
#include <tuple>

int main()
{
    using int_types = std::tuple<int, long, short, char>;
    std::cout << std::tuple_size_v<int_types> << ' '
        << typeid(std::tuple_element_t<2, int_types>).name();
}

MSVC输出:

4 short

GCC 输出:

4 s

Clang 输出:

4 s

评论

0赞 max66 6/16/2019
不确定,但我怀疑 OP 更喜欢而不是 .std::tuple_element_tstd::tuple_element
0赞 Aykhan Hagverdili 6/16/2019
@max66是的,我想是的。谢谢你指出,现在更有意义了
0赞 sbi 6/17/2019
我可以使用元组(),但我需要像他的答案中所示的max66那样包装它,因为有时(见这里我可能不得不实例化它。+1
3赞 max66 6/16/2019 #2

在我看来,在现代 C++ 标准库中,最接近您想要的是 .std::tuple

如果问题是所列类型的存储值(所以,我想,实例化该类型的对象可能是一个问题),那么很容易编写一个可实例化的对象,该对象包装了一个而不实例化本身。std::tuplestd::tupleusingstd::tuple

我的意思是。。。给定这样的包装器

template <typename ... Ts>
struct wrapTuple
 {
   using type = std::tuple<Ts...>;

   template <std::size_t N>
   using element = std::tuple_element_t<N, type>;

   static constexpr auto length { std::tuple_size_v<type> };
 };

您可以在不实例化包装器的情况下编写以下行

   using int_types = wrapTuple<int, long, short, char>;

   std::cout << int_types::length << ' '
      << typeid(int_types::element<2u>).name() << std::endl;

但你也可以实例化它,而不实例化std::tuple

   int_types it;

   std::cout << it.length << ' '
      << typeid(decltype(it)::element<2u>).name() << std::endl;

评论

0赞 sbi 6/17/2019
虽然这有效(),但这是一种丑陋的解决方法,需要文档才能让其他人理解它。那时我可能只使用我自己的类型列表模板。这些都很容易理解,好的命名可以传达目的,而不需要大量的文档来表达意图。+1
0赞 sbi 9/12/2019 #3

最后,我做了这样的事情:

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

template<typename    L> struct length;
template<typename ...T> struct length<type_list<T...>> {static const std::size_t value=sizeof...(T);};

template<std::size_t I, typename L>
struct element;
template<typename F, typename ...T> 
struct element<0, type_list<F, T...>> {using type=F;};
template<std::size_t I> 
struct element<I, type_list<>>        {using type=void;};
template<std::size_t I, typename F, typename ...T> 
struct element<I, type_list<F, T...>> {using type=typename element<I-1,type_list<T...>>::type;};

int main() {
    using int_types = type_list<int,long,short,char>;
    std::cout << length<int_types>::value << '\n'
              << typeid(element<2,int_types>::type).name() << '\n';
    return 0;
}