将二元组完美转换为一对

Perfectly transform a 2-tuple into a pair

我想要一个实用程序将 std::tuple<T,U> 转换为 std::pair<T,U>,同时保持 std::tuple<T, U, V, W...> 不变。

此外,我希望此实用程序

最后一点对我来说是困难的部分,这也是我问这个问题的原因。


我知道元组可以存储值和引用(左值引用和右值引用),所以想象一下,如果使用右值 2 元组提供所寻找的函数,它可以从非参考组件,但应完整保留参考组件。

例如给定

A a;
B b;
std::tuple<A, B&> t{a,b};

我知道 a 被复制到元组中,而 b 不是,我认为这样做

auto p{to_pair(t)};

应该生成一个 std::pair<A, B&>,其中包含 a 的另一个副本和对目前唯一存在的 b 的引用。

另一方面,做

B b;
auto p{to_pair(std::tuple<A, B&>{A{},b})};

应该会再次产生 std::pair<A, B&>,但是这会保留 A{} 的内容,永远不应该制作任何副本;无论如何它都会引用 b


以上描述的场景已经足够让我犹豫不决了,更别提去想&/const&/&&的其他组合了。

前段时间我有过一段苦日子,但我永远不能说我完全理解了他们。

template<class...Fs>
struct overloaded : Fs... {
  using Fs::operator()...;
};
template<class...Fs>
overloaded(Fs&&...)->overloaded<std::decay_t<Fs>...>;

auto move_tuples = []<class...Ts>(std::tuple<Ts...> x){return std::move(x);};
auto to_pair = []<class A, class B>(std::tuple<A, B> x){
  return std::pair<A,B>( std::get<0>(std::move(x)), std::get<1>(std::move(x)) );
};
auto your_function = overloaded{move_tuples, to_pair};

我想这就是你想要的。

我按值获取参数,然后将它们移动到 return 值。如果它们是值,则结果是移动包含的值。如果它们是引用,则它们不是,只是传播引用。

get<N> 在传递右值元组时“做正确的事”。如果 return 是一个值的右值。

中,您必须用手动结构替换 lambda。

或者写两个正常的重载,并且

auto obj=[](auto&&x)->decltype(normal_func(decltype(x)(x))){return decltype(x)(x);};

将重载函数调用normal_func转换为单个函数对象。