2

First option technically has less cognitive load because you don't need to be concerned with || or , operators. It is unfortunate that two nested lambdas are required to first get Is, and then to fold on the inner lambda. See cppreference fold expression examples and StackOverflow fold over pack.

// option 1
template<size_t N, typename... Ts> using nth =
    typename std::tuple_element<N, std::tuple<Ts...>>::type;

template <typename... Ts>
class type_list {
    // ...
public:
    template <typename T>
    constexpr auto locate()
    {
        std::size_t idx{sizeof...(Ts)};
        [&idx]<std::size_t... Is>(std::index_sequence<Is...>) {
            ([&idx]() {
                if (std::is_same_v<T, nth<Is, Ts...>>) {
                    idx = Is;
                }
            }(), ...);
        } (std::make_index_sequence<sizeof...(Ts)>{});
        return idx;
    }
};

Second option is shorter and benefits from short circuit evaluation. It feels easier to read - but perhaps deceptively, because the mechanism itself is more complicated. See DevTut fold over comma and StackOverflow fold over comma.

// option 2
template <typename... Ts>
class type_list {
    // ...
public:
    template <typename T>
    constexpr auto locate() {
        return [] <std::size_t... Is> (std::index_sequence<Is...>) {
            std::size_t idx{sizeof...(Ts)};
            ((idx = Is, std::is_same_v<T, Ts>) || ...);
            return idx;
        } (std::make_index_sequence<sizeof...(Ts)>{});
    }
};

In C++26, we will hopefully get for... and until then, what is considered more idiomatic?

Okay, maybe "idiomatic" isn't the right word. Which of these compile time compatible looping structures is least offensive, in place of first class language support for parameter packs and folding on control flow, to perform basic variadic template metaprogramming in C++20?

okovko
  • 1,851
  • 14
  • 27

0 Answers0