How to get element reference of a tuple using a predicate?

Viewed 154

It's my first post on Stackoverflow.

I'm currently hurting a problem. I have a code working outside of a class(or struct) but when I put into a class it's failed.

My objective is to be able to get a reference of a tuple element using a predicate.

So I found here https://www.fluentcpp.com/2019/03/08/stl-algorithms-on-tuples/ an example of find_if for tuple.

It works great.

So I get an index of tuple where my element is.

Now it's easy i can use std::get to get my reference.

My sample worked in a main.cpp So i decided to clean it by moving this into my class to get an api of the form :

constexpr T& MyStruct::get(const char* name).

But now my code is not compiling. The commented code is not compiling :

#include <tuple>
#include <iostream>

/******************************************************************************************************/
//Helper to find tuple element index


template <class Tuple, class F, std::size_t... I>
constexpr F for_each_impl(Tuple&& t, F&& f, std::index_sequence<I...>)
{
    return (void)std::initializer_list<int>{(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))), 0)...}, f;
}

template <class Tuple, class F>
constexpr F for_each(Tuple&& t, F&& f)
{
    return for_each_impl(std::forward<Tuple>(t), std::forward<F>(f),
        std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
}

template<typename Tuple, typename Predicate>
constexpr size_t find_if(Tuple&& tuple, Predicate pred)
{
    size_t index = std::tuple_size<std::remove_reference_t<Tuple>>::value;
    size_t currentIndex = 0;
    bool found = false;
    for_each(tuple, [&](auto&& value)
        {
            if (!found && pred(value))
            {
                index = currentIndex;
                found = true;
            }
            ++currentIndex;
        });
    return index;
}
/***********************************************************************************************/

template <typename T>
struct LabelType {

    constexpr LabelType(const char* label, T val) : _label(label), _value(val) {}

    const char* _label;
    T _value;
};

template <typename ...Args>
struct LabelList {

    constexpr LabelList(Args... args) : _tuple(std::forward<Args>(args)...) {}

    //constexpr auto& get(const char* name) const {
    //    constexpr auto index = find_if(_tuple, [&](const auto& type) {
    //        return type._label == name;
    //        });

    //    return std::get<std::tuple_element_t<index, std::tuple<Args...>>>(_tuple);
    //}

    std::tuple<Args...> _tuple;
};



int main() {
    constexpr auto list = LabelList{
        LabelType{"int label", 123},
        LabelType{"string label", "hello world"},
        LabelType{"float label", 3.14f},
        LabelType{"bool label", false},
    };

    constexpr auto index = find_if(list._tuple, [&]( const auto& type) {
        return type._label == "string label";
        });

    constexpr auto& string_ref = std::get<std::tuple_element_t<index, decltype(list._tuple)>>(list._tuple);

    std::cout << string_ref._label << " - " << string_ref._value;


    //constexpr auto& string_ref2 = list.get("string label");

    //std::cout << string_ref2._label << " - " << string_ref2._value;
}

If someone have any idea to fix it or an other way to do what I want?

0 Answers
Related