我正在尝试编写一个元组,而我还没想到的一件事是如何编写一个交换。 (简化)类型如下所示:
template<size_t I, typename T>
struct tuple_elem {
...
void swap(tuple_elem& other)
{
// implemented
}
};
template<size_t... Is, typename... Ts>
struct tuple_impl<std::index_sequence<Is...>, Ts...>
: private tuple_elem<Is, Ts>...
{
void swap(tuple_impl& other)
{
// ???
}
};
我一直在尝试在// ???
标记的地方解压缩索引和类型,但在我的生活中不能弄清楚如何。我尝试过这样的事情:
static_cast<tuple_elem<Is, Ts>&>(*this)->swap(
static_cast<tuple_elem<Is, Ts>&>(other))...;
但是给出了错误:
Tuple.hpp:182:64: error: expected ';' before '...' token
static_cast<tuple_elem<Is, Ts>&>(other))...;
^~~
Tuple.hpp:182:67: error: parameter packs not expanded with '...':
static_cast<tuple_elem<Is, Ts>&>(other))...;
^
帮助!
答案 0 :(得分:0)
好的,首先。通过以您尝试的方式扩展包,您将无法获得有效的表达。试着写出来。
现在我将从最简单的开始。 (我假设你正在实现一个元组,所以你有一些标准的实用程序std::tuple
。)如果你的编译器实现了C ++ 17的fold表达式,那么交换就可以这么简单:
template<typename... Tn, typename... Tn2, size_t... Is>
void swap_impl(tuple<Tn...>& a, tuple<Tn2...>& b, std::index_sequence<Is...>)
{
using std::swap;
(swap(get<Is>(a), get<Is>(b)), ...);
}
使用两个元组和std::index_sequence_for<Is...>{}
调用。 get<I>(tuple)
易于实施,这是您static_cast<tuple_elem<Is, Ts>&>(tuple)
的事情。
另一方面,如果您只能访问C ++ 14,我的方法将如下所示:
template<size_t N>
struct tuple_ops
{
template<typename T, typename T2, size_t I = tuple_size<T>::value - N>
static constexpr void swap(T& a, T2& b)
{
using std::swap;
swap(get<I>(a), get<I>(b));
return tuple_ops<N - 1>::swap(a, b);
}
};
显然,与任何递归方法一样,您需要为0提供基本情况。
template<>
struct tuple_ops<0>
{
template<typename T, typename T2>
static constexpr void swap(T&, T2&) noexcept {}
};
然后您的交换功能如下:
constexpr void swap(tuple& rhs) {
tuple_ops<sizeof...(Tn)>::swap(*this, rhs);
}
注意:代码未经测试。