如何在可变模板上生成递归数据结构
How do I generate recursive data structures on variadic templates?
我试图掌握递归数据结构生成技术使用TMP解决这个问题。
假设我有一个可变模板 template<typename... Ts> struct my_sets { };
。
在my_sets
中,我想生成一个新的类型,其数据成员依赖于Ts
。
例如,我希望my_sets
对Ts...
std::set<T>
数据成员using x_t = my_sets<int,char,std::string>;
x_t x;
x.insert<0>( 5 ); // into a std::set<int> member in my_sets<>
x.insert<1>( 'z' ); // into a std::set<char> member in my_sets<>
x.insert<2>( "foo" ); // into a std::set<std::string> member in my_sets<>
我认为实现这一点的一种方法可能是通过使用子类化和递归,但我不确定。
当然,如果通过自由函数或普通函数重载实现mutator更直接,也可以:
insert<0>( x, 5 ); // into a std::set<int> member in my_sets<>
insert<1>( x, 'z' ); // into a std::set<char> member in my_sets<>
insert<2>( x, "foo" ); // into a std::set<std::string> member in my_sets<>
这里std::tuple
有什么问题?
#include <tuple>
#include <set>
template<class... Ts>
using my_sets = std::tuple<std::set<Ts>...>;
// ...
auto x = my_sets<int, char, std::string>;
std::get<0>(x).insert(5);
std::get<1>(x).insert('z');
std::get<2>(x).insert("foo");
为外观添加一个免费的insert
函数:
#include <utility>
template<std::size_t I, class SetTuple, class Arg>
auto insert(SetTuple& st, Arg&& arg)
-> decltype(std::get<I>(st).insert(std::forward<Arg>(arg)))
{
return std::get<I>(st).insert(std::forward<Arg>(arg));
}
@Xeo有一个优雅而简单的解决方案。但是,如果您希望将insert<>
作为成员函数,则可以使用以下方法:
#include <set>
#include <tuple>
template<typename... Ts>
struct my_sets : protected std::set<Ts>...
{
using types = std::tuple<Ts...>;
template<int I, typename T>
typename std::pair<
typename std::set<typename std::tuple_element<I, types>::type>::iterator,
bool> insert(T&& t)
{
return std::set<typename std::tuple_element<I, types>::type>::insert(
std::forward<T>(t)
);
}
// ...
// Function for retrieving each set...
template<int I>
typename std::set<typename std::tuple_element<I, types>::type>& get()
{
return *this;
}
};
你可以这样使用
#include <string>
int main()
{
my_sets<int, double, std::string> s;
s.insert<0>(42);
s.insert<1>(3.14);
s.insert<2>("Hello World!");
s.get<0>().insert(42);
}
请注意,上面的解决方案不允许在类型列表中多次出现相同的类型(这可能是也可能不是期望的),尽管它可以很容易地扩展为允许它们:
#include <set>
#include <tuple>
namespace detail
{
template<int... Is>
struct indices
{
typedef indices<Is..., sizeof...(Is)> next;
};
template<int I>
struct index_range
{
using type = typename index_range<I - 1>::type::next;
};
template<>
struct index_range<0>
{
using type = indices<>;
};
template<int I, typename T>
struct dummy : T { };
template<typename, typename... Ts>
struct my_sets { };
template<int... Is, typename... Ts>
struct my_sets<indices<Is...>, Ts...> : protected dummy<Is, std::set<Ts>>...
{
using types = std::tuple<Ts...>;
template<int I, typename T>
typename std::pair<
typename std::set<typename std::tuple_element<I, types>::type>::iterator,
bool
> insert(T&& t)
{
return dummy<I, std::set<typename std::tuple_element<I, types>::type>>::
insert(std::forward<T>(t));
}
template<int I>
dummy<I, std::set<typename std::tuple_element<I, types>::type>>& get()
{
return *this;
}
};
}
template<typename... Ts>
using my_sets = detail::my_sets<
typename detail::index_range<sizeof...(Ts)>::type,
Ts...
>;
你可以这样使用它:
#include <string>
int main()
{
my_sets<int, double, int, std::string> s;
s.insert<0>(42);
s.insert<1>(3.14);
s.insert<2>(1729);
s.insert<3>("Hello World!");
s.get<0>().insert(42);
}
相关文章:
- 二叉树结构平衡,使用递归时EXC_BAD_ACCESS
- 如何在C++中表示JSON文档的递归对象结构?
- 查找存储在二叉搜索树的所有非叶子中的数据总和?(返回整数的独立递归函数
- 如何将从第 2 个字符开始的字符串作为函数中的参数传递以进行递归,并约束数据 tiee 是函数中的字符串?
- C++ 递归返回 nullptr 中的结构 ?.
- 递归如何使用堆栈数据结构
- 递归定义数组中的数据对齐和排序
- 使用boost::序列化递归图结构时,如何防止堆栈溢出
- 协议缓冲区、Apache Thrift或任何其他数据结构序列化协议中的递归数据结构
- 递归类型真的是构建不连续的任意大小数据结构的唯一方法吗
- 递归数据结构的前向声明
- 如何编写递归函数来计算图形数据结构中的最短路径
- 模板化的递归数据类型
- 用于树数据结构的递归函数
- 共享指针递归地删除递归数据结构,堆栈溢出
- C++、正向声明和递归数据类型
- 递归排列,Ellis Horowitz算法和数据结构混淆
- 如何在可变模板上生成递归数据结构
- 在<T>递归数据结构中移动unique_ptr数组
- 递归地从嵌套的通用数据结构中获取项