在constexpr数据数组

时间:2016-04-01 20:09:32

标签: c++

我正在尝试在编译时创建一个跳转表,然后在运行时使用它。它可以这样工作:

struct blah { constexpr blah() {} int operator()() const { return 42; }};
int fun(std::string const& str)
{
    return switch_ {
        case_{ "hello"_s, [](){ return 5; }
        case_{ "blah"_s, blah{} }
    }(str);
}

在这种情况下,_sconstexpr string

这个想法是,这将使用constexpr哈希函数在编译时创建一个哈希表。

我相信我已经解决了每个问题,除了一个问题,如果解决不了可能会使这个想法无法实现。那是初始化。

哈希是用数组实现的。碰撞将放置在该阵列中的空单元格中。因此,我需要找到一种方法将所有数据类型存储为单一类型。基本类型的擦除技术似乎不起作用。也不能使用placement new或将值转换为字节并将它们复制到数组中。还尝试使用UB调用联合技巧,该技巧通常在运行时工作,但在constexpr上下文中是不允许的。

似乎唯一可用的选项是渲染一个实际上更像是元组的排序联合。因此它只存储一个值,但占用散列中所有类型的内存。这对我来说似乎并不好。

那么,有人能想到一种将任意类型存储到constexpr生成的数组中的方法吗?

1 个答案:

答案 0 :(得分:0)

我认为没有一般方法可以解决您的问题。但是在最近的字符串文字的情况下,我提出了一种(非完美的)将它作为参数传递给模板类的方法,你可以找到它here

使用它你可以创建一种由字符串文字索引的数组,例如:专业化:

#include <iostream>
#include <functional>

#include "string_literal.h"

template <class SLiteral>
struct switch_;

template <>
struct switch_<STRING_LITERAL(3, "abc")> {
   int do_something() { return 1; }
};

template <>
struct switch_<STRING_LITERAL(12, "123456789012")> {
   int do_something() { return [](){ return 5;}(); }
};

template <>
struct switch_<STRING_LITERAL(8, "blahblah")> {
   std::function<int()> foo;
   template <class T>
   switch_(T t) {
      foo = t;
   }
   int do_something() { return foo(); }
};

int main() {
   std::cout << switch_<STRING_LITERAL(3, "abc")>().do_something() << std::endl;
   std::cout << switch_<STRING_LITERAL(12, "123456789012")>().do_something() << std::endl;
   std::cout << switch_<STRING_LITERAL(8, "blahblah")>([](){return 10;}).do_something() << std::endl;
}

程序的输出是:

1
5
10