首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实例化用于编译时/静态多态性的类型列表

如何实例化用于编译时/静态多态性的类型列表
EN

Stack Overflow用户
提问于 2021-03-28 11:07:26
回答 2查看 322关注 0票数 1

我正在实现一个使用静态多态和元编程的编译时调度程序。

我有一个类型列表,我想将这些类型实例化到运行时std::array中。

代码语言:javascript
复制
struct Test
{
     typedef std::integral_constant<int,0> nop;
     typedef std::integral_constant<int,1> A;
     typedef std::integral_constant<int,2> B;
     typedef std::integral_constant<int,3> C;

     using list = mp_list<A, B, C>; // mp_list expands to: template<A, B, C> struct {};

     struct Things{
         int (Test::*process)(int foo, float bar);
         const std::string key;
         int something;
         float other;
     };

     typedef std::array<Things, mp_size<list>::value> Thing_list;
     Thing_list thing_list;

     template<typename T=nop> int process(int foo, float bar);

     // stuff...

     Test();
}

在上面的代码中,mp_list只是一个“扩展”到struct<A, B, C> mp_list的可变模板。同样,mp_size给出了sizeof的mp实现。

可以推断,Thing_list是一个具有编译时已知大小的数组.

然后我可以专门化一个模板函数,如下所示:

代码语言:javascript
复制
template<> int process<Test::B>(int foo, float bar){ /* do stuff */ };

以实现编译时多态。

上面的代码工作得很好,只是为了初始化它,我不得不在构造函数中这样做:

代码语言:javascript
复制
Test::Test() thing_list({{{&Test::process<A>, "A"}, // this all should be achieved through meta-programming
                          {&Test::process<B>, "B"},
                          {&Test::process<C>, "C"}}}} )
{
   // stuff
}

有两件事我做不好:

  1. I希望对列表进行基于MP的初始化。在更新声明中的list定义时,我希望初始化时自动反映该列表类型,
  2. 也希望避免将类型的名称复制为字符串文本。我尝试过使用类似于integral_constant的东西,但是使用const char*作为模板参数似乎是被禁止的。我不得不重复声明(一式三份,真的)。

This答案几乎就是解决方案:它接受类型的列表并实例化它们,如下所示:

代码语言:javascript
复制
static std::tuple<int*, float*, foo*, bar*> CreateList() {
return { Create<int>(), Create<float>(), Create<foo>(), Create<bar>() };
}

但是,我仍然停留在从std::tuple转换到std::array上。

主要的问题是#1.不使用基于#define的诡计的第二种奖励。

如果有人关心的话:这段代码注定要用于嵌入式软件。有几十种不同的类型,重要的是,每种类型(例如ABC)都将有一个结构相同的配置从内存中加载(例如,在"A"的配置键下)--因此需要在运行时访问该类型的字符串名称。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-28 14:58:57

我建议将A、B和C的typedefs更改为struct,这样您就可以在其中定义字符串。

代码语言:javascript
复制
struct A {
    static constexpr int value = 1;
    static constexpr char name[] = "A";
};

// Same for B and C

using list = mp_list<A, B, C>;

然后您可以创建一个make_thing_list

代码语言:javascript
复制
template <typename... T>
static std::array<Things, sizeof...(T)> make_thing_list(mp_list<T...>) {
    return {{{&Test::process<T>, T::name}...}};
}

auto thing_list = make_thing_list(list{});

完整示例

代码语言:javascript
复制
#include <string>
#include <array>
#include <iostream>

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

struct Test
{
    struct nop {
        static constexpr int value = 0;
        static constexpr char name[] = "nop";
    };
    struct A {
        static constexpr int value = 1;
        static constexpr char name[] = "A";
    };
    struct B {
        static constexpr int value = 2;
        static constexpr char name[] = "B";
    };
    struct C {
        static constexpr int value = 3;
        static constexpr char name[] = "C";
    };

     using list = mp_list<A, B, C>; // mp_list expands to: template<A, B, C> struct {};

     struct Things{
         int (Test::*process)(int foo, float bar);
         const std::string key;
         int something;
         float other;
     };

    template <typename... T>
    static std::array<Things, sizeof...(T)> make_thing_list(mp_list<T...>) {
        return {{{&Test::process<T>, T::name}...}};
    }

    using Thing_list = decltype(make_thing_list(list{}));

    Thing_list thing_list = make_thing_list(list{});

     template<typename T=nop> int process(int foo, float bar) {
         return T::value;
     }

     // stuff...

     Test() {}
};

int main() {
    Test t;

    static_assert(std::is_same_v<decltype(t.thing_list), std::array<Test::Things, 3>>);

    for (auto& thing : t.thing_list) {
        std::cout << thing.key << (t.*thing.process)(1, 1.0) << '\n';
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-03-28 13:00:02

不知道你到底想要什么但是..。

考虑到至少可以使用C++17 (对于auto模板参数),您可以将类外部的一些变量定义为

代码语言:javascript
复制
static constexpr char nops[] = "NOP";
static constexpr char A[] = "A";
static constexpr char B[] = "B";
static constexpr char C[] = "C";

然后是一个接受nopsAB等模板参数的简单包装器。

代码语言:javascript
复制
template <auto val>
struct wrap
 { };

然后,给出一个模板值参数的可变列表的using,创建一个wrap类型的mp_list

代码语言:javascript
复制
template <auto ... vals>
using wrapper = mp_list<wrap<vals>...>;

现在..。我想,在Test中,您可以定义noplist,如下所示

代码语言:javascript
复制
using nop = wrap<nops>;

using list = wrapper<A, B, C>;

使用委托构造函数来初始化thing_list的元编程方法可以如下所示

代码语言:javascript
复制
template <auto ... vals>
Test (mp_list<wrap<vals>...>) 
   : thing_list{{{&Test::process<wrap<vals>>, vals}...}}
 { }

Test () : Test{list{}}
 { }

如果修改list,添加一个D参数(其中D"D"文本)

代码语言:javascript
复制
using list = wrapper<A, B, C, D>;

自动地,您将在您的{&Test::process<wrap<D>>, D}中获得一个额外的thing_list元素。

下面是一个完整的编译C++17示例

代码语言:javascript
复制
#include <array>
#include <string>
#include <type_traits>

template <typename...>
struct mp_list
 { };

template <typename>
struct mp_size;

template <typename ... Ts>
struct mp_size<mp_list<Ts...>>
   : public std::integral_constant<std::size_t, sizeof...(Ts)>
 { };

static constexpr char nops[] = "NOP";
static constexpr char A[] = "A";
static constexpr char B[] = "B";
static constexpr char C[] = "C";

template <auto val>
struct wrap
 { };

template <auto ... vals>
using wrapper = mp_list<wrap<vals>...>;


struct Test
 {
   using nop = wrap<nops>;

   using list = wrapper<A, B, C>;

   struct Things
    {
      int (Test::*process)(int foo, float bar);
      const std::string key;
      //   int something;
      //   float other;
    };

   using Thing_list = std::array<Things, mp_size<list>::value>;

   Thing_list thing_list;

   template<typename T=nop> int process(int foo, float bar)
    { return 0; }

   template <auto ... vals>
   Test (mp_list<wrap<vals>...>) 
      : thing_list{{{&Test::process<wrap<vals>>, vals}...}}
    { }

   Test () : Test{list{}}
    { }
 };

int main ()
 {
   Test  t;
 }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66840757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档