替换std :: tuple的第N个元素

问题描述 投票:0回答:1

用新的类型和值替换元组的第n个元素的最短/最佳方法是什么(包括c ++ 20的解决方案很好)?

即:

#include <cassert>
#include <tuple>

template<std::size_t N, ... >
auto replace_tuple_element( ... ) // <- Looking for a suitable implementation

struct Foo {
    int value;
};

int main()
{
    auto t1  = std::tuple{ 0, 1, 2, 3 };
    auto t2 = replace_tuple_element<2>( t1, Foo{10} );

    assert( std::get<0>(t2) == std::get<0>(t1));
    assert( std::get<1>(t2) == std::get<1>(t1));
    assert( std::get<2>(t2).value == 10);
    assert( std::get<3>(t2) == std::get<3>(t1));
}

注意:只需替换类型列表中的第n个类型,例如在这里讨论:How do I replace a tuple element at compile time?。但是我也想替换它的价值,并希望现在c ++ 20中有比问这个问题时更简单/更优雅的解决方案。

c++ c++20
1个回答
0
投票

我为c ++ 20找到的一个解决方案是这样:

#include <cassert>
#include <tuple>
#include <type_traits>

template<std::size_t N, class TupleT, class NewT>
constexpr auto replace_tuple_element( const TupleT& t, const NewT& n )
{
    constexpr auto tail_size = std::tuple_size<TupleT>::value - N - 1;

    return [&]<std::size_t... I_head, std::size_t... I_tail>
        ( std::index_sequence<I_head...>, std::index_sequence<I_tail...> )
        {
            return std::tuple{
                std::get<I_head>( t )...,
                n,
                std::get<I_tail + N + 1>( t )...
            };
        }(  
           std::make_index_sequence<N>{}, 
           std::make_index_sequence<tail_size>{} 
          );
}

struct Foo {
    int value;
};

int main()
{
    auto t1  = std::tuple{ 0, 1, 2, 3 };
    auto t2 = replace_tuple_element<2>( t1, Foo{10} );

    assert( std::get<0>(t2) == std::get<0>(t1));
    assert( std::get<1>(t2) == std::get<1>(t1));
    assert( std::get<2>(t2).value == 10);
    assert( std::get<3>(t2) == std::get<3>(t1));
}

我喜欢该解决方案的地方是它是一个单一的自包含函数。我不知道是否有更短和/或更易读的内容。

© www.soinside.com 2019 - 2024. All rights reserved.