4

I'm currently doing some work and I would like to abstract as much code as possible into a simple api. Essentially I want to write something like this:

int main()
{
    Server server;

    server.get<"/hello">([] { std::cout << "hello" << std::endl; });
    server.get<"/goodbye">([] { std::cout << "goodbye" << std::endl; });

    server.listen();
}

and have it create the necessary regex (using CTRE) at compile time.

However, when I need to match with these regexes, I need to have a list of them, so that I can loop through them and check each one. This has proven very difficult. One thing I've tried is to create something like this:

template<typename Contained>
class Container {
public:

    constexpr Container() = default;
    ~Container() = default;

    constexpr void add(Contained&& item) { m_temp_container.push_back(item); }

    constexpr size_t arr_size() const {
        size_t a = 64;
        while(true)
        {
            if (size() > a) a+=64;
            else break; 
        }
        return a;
    }

    constexpr auto array() const {
        constexpr size_t s = arr_size();
        std::array<Contained, s> array;
        for(int i = 0; i < size(); i++)
            array[i] = std::move(m_temp_container[i]);
        return array;
    }

    constexpr size_t size() const { return m_temp_container.size(); }

    std::vector<Contained> m_temp_container;

};

struct CString
{
    constexpr CString() : m_a(nullptr) {};
    constexpr CString(const char* a) : m_a(a) {}
    ~CString() = default;

    const char* m_a;
};

int main()
{

    Container<CString> container;

    container.add("hello");
    container.add("there");
    container.add("how");
    container.add("are you");

    const auto arr = container.array();
}

however, the compiler complains that

constexpr size_t s = arr_size();

is not a constant expression.

I'm not sure creating a list like this is even possible, at least not with my current knowledge of the standard library.

I could probably do this by having the user pass the Handlers as a complete object, perhaps by doing something like this:

int main()
{
    constexpr auto get_handlers = {
        Handler<"/hello">([] {...} ),
        Handler<"/hello2">([] {...} )
    };

    Server server(get_handlers, ...);

    server.listen();
}

but I would still like to know if it's in any way possible to construct a list by code at compile time and loop through it as if it were a const array at runtime.

Any ideas?

Thomas
  • 41
  • 1
  • Not the answer, but have you seen [cpp-httplib](https://github.com/yhirose/cpp-httplib)? It provides almost the same API you want, except regexes are resolved at runtime. – HolyBlackCat Oct 29 '21 at 16:23
  • 2
    Why do you need a constexpr list? Since you'll loop over regexes at runtime anyway, might as well use a plain `std::vector`? – HolyBlackCat Oct 29 '21 at 16:24
  • You cannot have constexpr `std::vector` even in C++20. – Jarod42 Oct 29 '21 at 16:31
  • Is the "passing the handlers as a complete object" not the same thing as what you want? – user253751 Oct 29 '21 at 16:40
  • Yes I have seen cpp-httplib, and I'm currently working on a similar internal project. I'm using it as reference, but I'm also planning on not using std::regex. I don't need a constexpr list, but the question is more if this is possible in c++. Building the array at compile time, so to speak. Passing the handlers as a complete object is possible, but it's also not how I want my API to look. I'm just wondering if there is a way to tell the compiler that I essentially want a const array based on the constructed dynamic list. – Thomas Oct 29 '21 at 17:32
  • How about something along these general lines: https://gcc.godbolt.org/z/h54G9shYP Where each call to `get<>` returns a new server with the handler appended to it. (obviously needs more work to make it nice) –  Oct 29 '21 at 18:10
  • I really like your example Frank, and I think this might just be the way to go for now. Clever! – Thomas Oct 30 '21 at 17:38
  • @Jarod42 you definitely can with transient allocations. – Mechap Oct 31 '21 at 08:59
  • @Mechap: regular `std::vector` can be used in constexpr functions, but cannot outlive the constexpr function. so `constexpr Container` is currently not possible. but OP can create function to return a `std::array`. – Jarod42 Oct 31 '21 at 11:38

0 Answers0