1

I'm experimenting with the idea of creating a jump table at compile time that is then used during runtime. It would work something like so:

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);
}

In this case, _s is a constexpr string.

The idea is that this will create a hash table at compile time using a constexpr hash function.

I believe I have solved every issue with exception to one, which if it can't be solves probably makes this idea impossible to implement. That is initialization.

The hash is implemented with an array. Collisions will get placed in empty cells within that array. So then I am required to find a way to store all data types as a single type. Basic type erasure techniques don't appear to work. Also can't use placement new or cast the value into bytes and copy them into an array. Also tried to use a UB invoking union trick that generally would work at runtime but isn't allowed in constexpr context.

The only option that seems to be available is to render a union of sorts that is actually more like a tuple. So it only stores one value but occupies memory of all types in the hash. This doesn't seem good to me.

So, can anyone think of a way to store an arbitrary type into a constexpr generated array?

2

1 Answer 1

0

I don't think there's a general way to solve your problem. But in case of the string literal recently I proposed a (not perfect) way of passing it to template class as parameter you can find it here.

Using this you could create kind of array indexed by the string literal e.g. by specialization:

#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;
}

output of a program is:

1
5
10
Sign up to request clarification or add additional context in comments.

2 Comments

I'm narrowing in on a solution. See the comment to my OP.
@CrazyEddie I looked through your code. After reading your question and pseudo code I got the impression that you want to implement constexpr map (indexed with the arbitrary constexpr type) rather than the array of constexpr type. Sorry, I've misunderstood your question...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.