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

Mik*_*eMB 7 c++ c++20

用一个值(可能有也可能没有不同的类型)替换元组的第 n 个元素的最短/最佳方法是什么?包括 c++20 在内的解决方案很好。[编辑:我更喜欢不需要其他库的东西,但我仍然对使用例如 boost 可能的解决方案感兴趣]。

IE:

#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));
}
Run Code Online (Sandbox Code Playgroud)

注意:仅替换类型列表中的第 n 个类型已经在这里讨论过:如何在编译时替换元组元素?. 但我也想替换这个值,并希望现在在 c++20 中有比问这个问题时更简单/更优雅的解决方案。

Mik*_*eMB 5

我为 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));
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这个解决方案的地方在于它是一个单一的、自包含的函数。我想知道是否有更短和/或更易读的东西。