Search code examples
c++c++20stdtuplecompile-time-constant

accessing std::tuple element by constexpr in type


I would like to access to a tuple element at compile time by a value constexpr in the type

#include <iostream>
#include <tuple>
#include <utility>

struct A {
    static constexpr int id = 1;
    void work() {
            std::cout << "A" << std::endl;
    }
};

struct B {
    static constexpr int id = 2;
    void work() {
            std::cout << "B" << std::endl;
    }
};

int main() {
    A a;
    B b;
    std::tuple<A,B> t = std::make_tuple(a,b);

    static constexpr int search_id = 2;

    auto& item = std::get< ? ( T::id == search_id ) ? >(t);
    item.work();
    return 0;
}

I guess using std::apply and test would be a runtime search... I'm using c++20


Solution

  • You can create constrexpr function to get index:

    template <typename... Ts>
    constexpr std::size_t get_index(int id)
    {
        constexpr int ids[] = {Ts::id...};
    
        const auto it = std::find(std::begin(ids), std::end(ids), id);
    
        // Handle absent id.
        if (it == std::end(ids)) {
            throw std::runtime("Invalid id");
        }
        // You can also possibly handle duplicate ids.
    
        return std::distance(std::begin(ids), it);
    }
    
    template <int id, typename... Ts>
    constexpr auto& get_item(std::tuple<Ts...>& t)
    {
        return std::get<get_index<Ts...>(id)>(t);
    }
    template <int id, typename... Ts>
    constexpr const auto& get_item(const std::tuple<Ts...>& t)
    {
        return std::get<get_index<Ts...>(id)>(t);
    }
    

    and then

    auto& item = get_item<search_id>(t);