【问题标题】:List of values (of any types) as a template argument作为模板参数的值列表(任何类型)
【发布时间】:2016-05-22 03:28:33
【问题描述】:

我的类有一个静态 constexpr 成员函数 get,我需要它返回一个指向从模板参数生成的任意结构的第一个元素(声明为 char key;)的指针。

这就是我所拥有的:

template <char id, typename DataType, int... args>
struct MyStruct {
    static constexpr DataType member { id, args... };

    static constexpr void *get() {
        return(&member.key);
    }
};

只要 DataType 的所有成员(在第一个成员之后)都是 int 类型,这就会起作用,但是如果它们是 intvoid * 的混合呢?我应该如何更改模板以允许这样做?

这是用于语言之间的外来函数接口,因此另一端检查密钥,并据此知道内存中跟随它的结构类型。

【问题讨论】:

  • 当您在谈论void *参数时,您是在谈论void *的类型,还是在谈论constexpr void *的值?如果是后者,我不确定您打算如何创建它们,
  • @md5i 后者。它们适用于轻型伪 RTTI 系统。 template &lt;typename Type&gt; static constexpr void *makeTypeID()template &lt;typename Type&gt; struct TypeStore {static constexpr char placeholder = 0;} 中返回placeholder 的地址,并且该地址用作该类型的唯一标识符。当前的问题是如何在 TypeStore 中存储更多的数据来处理向量等数据结构。

标签: c++ templates c++11


【解决方案1】:

您不能发送任何类型的任何值作为模板参数。您不能发送结构值或浮点值或字符串文字。我提出了一个我认为可以取代任何需求的解决方案。

选项 1

只需定义一个带有返回对象的静态函数的结构。

struct Initializer {
    constexpr static SomeType initialize(char id) {
        return SomeType{id, 1.2, "blerg"};
    }
};

然后,将初始化器作为模板参数发送:

template <char id, typename Init> struct MyStruct {
    using DataType = decltype(Init::initialize(id));

    static constexpr DataType member = Init::initialize(id);     
    static constexpr void *get() {
        return(&member.key);
    }
};

选项 2

您可以将初始化函数放在打算为Datatype 的结构中,这样您就可以这样做:

DataType = DataType::initialize(id);

选项 3

在结构初始化器中,您也可以使用DataType 结构所需的所有额外参数创建一个元组。这将是您想要编写的代码中最接近的解决方案。初始化结构将如下所示:

struct Initializer {
    constexpr static std::tuple<float, const char*> args{1.5, "patate"};
    using args_t = decltype(args);
};

那你必须用整数序列解包:

template<char, typename, typename, typename> struct Base;

template<char id, typename DataType, typename Init, std::size_t... S>
struct Base<char, DataType, Init, std::index_sequence<S...>> {
    constexpr static DataType member{id, std::get<S>(Init::args)...};
};

您现在可以使用MyStruct 扩展Base

template <char id, typename DataType, typename Init> 
struct MyStruct : Base<id, DataType, Init,
    std::make_index_sequence<std::tuple_size<typename Init::args_t>::value>
> {
    static constexpr void *get() {
        return(&member.key);
    }
};

这些是一堆有用的解决方案。我敢肯定还有其他人。

【讨论】:

  • 我将每种类型的参数放在一个单独的参数包中,并为它们强制执行特定的顺序。这行得通,除了 Visual Studio 遇到stackoverflow.com/questions/23347287/… 之类的问题,所以看起来你的建议可能更干净、更灵活。我会试试看。
  • 在视频工作室上可能会更难。我建议你升级到最后一个版本,低于 2015 更新 1 的任何东西都会在constexpr 出现问题。
  • 注意第三个选项是使用c++14,如果你想让它使用c++11,你必须实现你的odn版本的std::tuplestd::get和@987654335 @。 tuples 和 get 从 c++14 开始只标记为 constexpr,而 index_sequence 是在 c++11 之后添加的。
猜你喜欢
  • 2017-11-19
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 2023-04-02
  • 2022-01-09
相关资源
最近更新 更多