如何返回嵌套在其他包中的模板包
How to return a template pack nested in other pack?
以下代码有效:
#include <iostream>
#include <list>
struct Base {};
struct A : Base {}; struct B : Base {}; struct C : Base {};
struct D : Base {}; struct E : Base {}; struct F : Base {};
template <int KEY, typename... RANGE> struct Map {}; // one-to-many map (mapping KEY to RANGE...)
template <typename...> struct Data {};
using Database = Data< Map<0, A,B,C>, Map<1, D,E,F> >;
template <int N, typename FIRST, typename... REST> // N has meaning in my program, but not shown here.
void insertInMenu (std::list<Base*>& menu) {
menu.push_back(new FIRST);
insertInMenu<N, REST...> (menu);
}
template <int N>
void insertInMenu (std::list<Base*>&) {} // End of recursion.
template <int N>
std::list<Base*> menu() {
std::list<Base*> m;
insertInMenu<0, A,B,C>(m); // A,B,C should be obtained using N and Database.
return m;
}
int main() {
std::list<Base*> m = menu<0>();
std::cout << "m.size() = " << m.size() << std::endl; // 3
}
但正如我在上面的评论中所指出的,我想使用Database
和值N
来获得范围A,B,C
(或D,E,F
)或其他什么。但我不知道该怎么做?有人能帮忙吗?线路
insertInMenu<0, A,B,C>(m);
需要用之类的东西来代替
obtainRange<Database, N>()
因为那些编译时已知的值应该是足够的信息来获得我想要的范围。
obtainRange<Database, 0>()
应返回A,B,C
和
obtainRange<Database, 1>()
在这种情况下应返回D,E,F
。
template <typename D, int N>
struct obtainRange;
template <int N, typename... Ts, typename... Maps>
struct obtainRange<Data<Map<N, Ts...>, Maps...>, N>
{
using type = std::tuple<Ts...>;
};
template <int N, int M, typename... Ts, typename... Maps>
struct obtainRange<Data<Map<M, Ts...>, Maps...>, N>
: obtainRange<Data<Maps...>, N> {};
template <int N, typename Tuple, std::size_t... Is>
std::list<Base*> menu(std::index_sequence<Is...>)
{
std::list<Base*> m;
insertInMenu<0, typename std::tuple_element<Is, Tuple>::type...>(m);
return m;
}
template <int N>
std::list<Base*> menu()
{
using Tuple = typename obtainRange<Database, N>::type;
return menu<N, Tuple>(std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
演示
如果您不能使用c++14std::index_sequence
,那么下面是一个与c++11兼容的替代实现:
template <std::size_t... Is>
struct index_sequence {};
template <std::size_t N, std::size_t... Is>
struct make_index_sequence_h : make_index_sequence_h<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct make_index_sequence_h<0, Is...>
{
using type = index_sequence<Is...>;
};
template <std::size_t N>
using make_index_sequence = typename make_index_sequence_h<N>::type;
您可以进一步使用类似于Data
和Map
的任意模板,例如Map
s的std::tuple
(而不是Data
),使用模板模板参数:
template <typename D, int N>
struct obtainRange;
template <template <typename...> class DB
, template <int, typename...> class MP
, typename... Ts
, typename... Maps
, int N>
struct obtainRange<DB<MP<N, Ts...>, Maps...>, N>
{
using type = std::tuple<Ts...>;
};
template <template <typename...> class DB
, template <int, typename...> class MP
, typename... Ts
, typename... Maps
, int M
, int N>
struct obtainRange<DB<MP<M, Ts...>, Maps...>, N> : obtainRange<DB<Maps...>, N> {};
演示2
// There is no need to take the length here, btw.
template <int, typename... Args>
void insertInMenu (std::list<Base*>& menu)
{
// Non-recursive push_backs:
std::initializer_list<int>{ (menu.push_back(new Args), 0)... };
}
template <int, typename> struct InsertEnv;
template <int key, int otherKey, typename... Args, typename... Rest>
struct InsertEnv<key, Data<Map<otherKey, Args...>, Rest...>> :
InsertEnv<key, Data<Rest...>> {};
template <int key, typename... Args, typename... Rest>
struct InsertEnv<key, Data<Map<key, Args...>, Rest...>>
{
void operator()(std::list<Base*>& menu)
{
insertInMenu<key, Args...> (menu);
}
std::list<Base*> operator()()
{
return {new Args...};
}
};
template <int N>
void addToMenu (std::list<Base*>& menu)
{
InsertEnv<N, Database>()(menu);
}
template <int N>
std::list<Base*> menu()
{
return InsertEnv<N, Database>()();
}
用户作为
menu<N>() // list with the desired elements in it
或作为
std::list<Base*> list;
addToMenu<N>(list); // pushes back the desired elements
演示。
住在Coliru
template <typename, int>
struct obtainRange {};
template <int N, typename...Types, typename...Rest>
struct obtainRange<Data<Map<N, Types...>, Rest...>, N> :
Data<Types...> {};
template <int N, typename T, typename...Rest>
struct obtainRange<Data<T, Rest...>, N> :
obtainRange<Data<Rest...>, N> {};
template <typename...Types>
std::list<Base*> menu(Data<Types...>) {
return { new Types{}... };
}
template <int N>
std::list<Base*> menu() {
return menu(obtainRange<Database, N>{});
}
相关文章:
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- AcquireCredentialsHandleA() 返回 PFX 文件的0x8009030e(安全包中没有可用的凭据
- MSYS2 MinGW程序包中缺少grpc_cpp_plugin协议
- 参数包中的筛选器类型
- 实例化模板时,我是否必须显式显示参数包中的类型?
- R 包中的 TMB c++ 代码和 CRAN 检查
- 擦除映射 c++ 中其他键的值中已存在的那些值
- C++ 在可变参数模板的参数包中并集参数?
- 如何检测参数包中的uint8_t类型
- 如何在 C# 中将带有参数的函数绑定到包中
- 从函数参数包中删除最后一项
- 从 Any 包中提取和匹配 protobuf 消息类型名的首选方法
- 如何使用Winforms C#或C++.Net在不更改文件中其他内容的情况下修改jpg文件中的Orientation e
- C++:我可以在模板参数包中强制执行至少1个agment吗
- 如何定义此"if block"中其他无效输入的值,以便在c ++中将字符串转换为对象?
- 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递
- 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?
- 在参数包中获取函数指针的返回类型,并将其保存为与其他参数连接的元组
- 使用Rcpp中其他包中的C函数
- 如何返回嵌套在其他包中的模板包