C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Accessing a tuple element of index not known until runtime

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sun, 12 Nov 2023 07:38:39 +0000
On 11 November 2023 23:35:05 GMT, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>If we have a tuple as follows:
>
> tuple<int,char,long> mytuple;
>
>Then we can access its elements as follows:
>
> get<0>(mytuple)
> get<1>(mytuple)
> get<2>(mytuple)
>
>The index must be a compile-time constant in order for it to be a
>template parameter to the template function "get". I've seen people
>write if-else ladders and switch statements:
>
> void SetNull(unsigned const index, tuple<int,char,long> &t)
> {
> switch ( index )
> {
> case 0: get<0>(t) = {}; break;
> case 1: get<1>(t) = {}; break;
> case 2: get<2>(t) = {}; break;
> default: unreachable();
> }
> }
>
>I think a lot of people would agree that the best way to allow runtime
>access of tuple elements would be to use the 'visit' function. Have
>there been any other proposals to simplify runtime access of tuple
>elements?

I'm not aware of any proposal, but there is a utility that does this in boost::mp11.

https://www.boost.org/doc/libs/1_70_0/libs/mp11/doc/html/mp11.html#mp_with_indexni_f

I agree that something like this is worth standardizing.

>My own version of 'visit' can be used as follows to set a tuple element to null:
>
> visit( index, mytuple, [](auto &x)
> {
> x = {};
> });
>
>Here's the code behind it:
>
>template<std::size_t I, typename ElemType, typename V>
>void visit_detail2(std::size_t const index, ElemType &&e, V &&v)
>{
> if ( I != index ) return;
> std::forward<V>(v)( std::forward<ElemType>(e) );
>}
>
>template<typename T, typename V, std::size_t... I>
>void visit_detail1(std::size_t const index, T &&t, V &&v,
>std::index_sequence<I...>)
>{
> (..., visit_detail2<I>(index,std::get<I>(std::forward<T>(t)),std::forward<V>(v)));
>}
>
>template<typename T, typename V>
>void visit(std::size_t const index, T &&t, V &&v)
>{
> visit_detail1(index, std::forward<T>(t), std::forward<V>(v),
> std::make_index_sequence< std::tuple_size_v<typename
>std::decay_t<T> > >());
>}


Both the standard variant and this tuple visit can be easily implemented with mp_with_index. I think we should standardise an mp_with_index-like utility, as that's the foundational building block that is hard to implement efficiently, and is the most generally useful.

Cheers,
Lénárd

Received on 2023-11-12 07:38:45