循环输入typedef

时间:2018-07-09 13:26:33

标签: c++ arrays metaprogramming typedef

对不起,标题有点误导。

我有一个循环一些数据的功能。每次迭代时,此数据的类型都会更改。

基本上我有这样的东西:

for(int i = 0; i < limit; i++)
{
  type object;
  object.do_stuff();
}

例如,在第一次迭代中,“ type”将为int,在第二次迭代中,“ type”将为double,等等。

我不能使用多变量模板,因为我有100多个元素,据我所知,这将对该系统造成很大的负担。

我的想法是创建一个“ typedefs向量”来循环所有类型的对象。

vector<????> type;
type.push_back(int);
type.push_back(double);
...
for(int i = 0; i < limit; i++)
{
  type[i] object;
  object.do_stuff();
}

我不知道这是否遥不可及。

我看到了类型列表的基础知识,但是我不知道是否有可能重现循环。

2 个答案:

答案 0 :(得分:7)

  

我不能使用多变量模板,因为我有100多个元素,据我所知,这将对该系统造成很大的负担。

您所知道的要么过时,要么不正确。只需看一下metaben.ch,您就可以了解如何在不影响编译时间的情况下获得较大的类型列表。


  

我的想法是创建一个“ typedefs向量”来循环所有类型的对象。

这是一个类型列表。您可以执行以下操作:

// Store the type in a value for convenience
template <typename T>
struct type_wrapper
{
    using type = T;
};

template <typename... Ts>
struct typelist
{
    template <typename F>
    constexpr void for_each(F&& f)
    {
        // C++17 fold expression over comma operator
        (f(type_wrapper<Ts>{}), ...);
    }
};

C ++ 17用法:

typelist<int, float, char>{}.for_each([](auto t)
{
    using type = typename decltype(t)::type;
    // Use `type`
});

C ++ 20的用法(对typelist进行了较小的更改):

template <typename... Ts>
struct typelist
{
    template <typename F>
    constexpr void for_each(F&& f)
    {
        // C++17 fold expression over comma operator
        (f.template operator()<Ts>(), ...);
    }
};

typelist<int, float, char>{}.for_each([]<typename T>()
{
    // Use `T`
});

我写了一篇与此主题有关的简短文章:"compile-time iteration with C++20 lambdas "

答案 1 :(得分:0)

我们可以用一种稍微不同的方式来看待这个问题,并说您也许真正想要的是要做的事情的向量(或者,也许我想说,列出) ,并且可以使用中的某些工具以非常通用的方式实现。让我们看一下:

#include <vector>
#include <functional>
#include <iostream>

static void process_int (int i) { std::cout << "process_int " << i << "\n"; }
static void process_string (std::string s) { std::cout << "process_string " << s << "\n"; }
// ...                                            

int main()
{
    std::vector <std::function <void ()>> v;

    v.push_back (std::bind (process_int, 42));
    v.push_back (std::bind (process_string, "Hello world"));

    for (auto f : v)
        f ();                    
}

输出:

process_int 42
process_string Hello world

这很难简单,可以,并且您可以采用各种聪明(或不太聪明)的方式来适应特定的用例。如现场演示所示,在C ++ 11中应该没问题。您还可以将lambda传递给std::bind

Live demo