参数包模板元编程深度优先搜索
Parameter pack template metaprogramming depth first search
我有一个这样的参数类:
template <class KEY, class VALUE>
class parameter
{
VALUE v;
...
};
我有一个参数包类:
template <class... ELEMENTS>
class parameter_pack
{
std::tuple<ELEMENTS...> elems;
};
parameter_packs
包含许多parameters
和/或parameter_packs
。
我想要一个如下所示的函数(或方法(:
template <class KEY_TO_GET, class PARAMETER_PACK>
... get_value(const PARAMETER_PACK& p) { ... }
这将对具有KEY
值的第一个parameter
执行深度优先遍历并返回其值。当然,这应该在编译时完成,并且应该有恒定的运行时。请注意KEY
这里只是一个空类,永远不会创建或使用。
我希望能够从左边或右边做到这一点。
这个想法是你可以有一组默认参数,你可以将它们保存到一个变量中,并在将它们传递给函数之前覆盖。我不认为 boost::p arameter 允许保存(由于对临时的引用(,我相信当您在参数上加倍时它会出错。
我可能弄错了,但它不是类似于您正在寻找的代码吗?
#include <iostream>
#include <utility>
class nill
{
};
template<typename KEY, typename VALUE, VALUE v>
class parameter
{
public:
typedef KEY key_type;
typedef VALUE value_type;
static constexpr VALUE value = v;
};
template<typename ...>
class parameter_pack
{
};
template<typename KEY, typename P>
class get_param;
template<typename KEY, typename H, typename ...TAIL>
class get_param<KEY, parameter_pack<H, TAIL...>>
{
private:
typedef typename get_param<KEY, H>::type result;
public:
typedef typename std::conditional<std::is_same<result, nill>::value,
typename get_param<KEY, parameter_pack<TAIL...>>::type, result>::type
type;
};
template<typename KEY>
class get_param<KEY, parameter_pack<>>
{
public:
typedef nill type;
};
template<typename KEY, typename K, typename V, V v>
class get_param<KEY, parameter<K, V, v>>
{
public:
typedef typename std::conditional<std::is_same<K, KEY>::value,
parameter<K, V, v> , nill>::type type;
};
template<unsigned T>
class tag
{
};
int main()
{
typedef parameter_pack
<
parameter_pack
<
parameter<tag<0>, int, 0>
>,
parameter_pack
<
parameter<tag<4>, int, 42>,
parameter<tag<2>, int, 1>,
parameter_pack
<
parameter<tag<3>, int, 100>,
parameter<tag<4>, int, 5>,
parameter<tag<0>, int, 33>,
parameter<tag<2>, int, 666>
>
>,
parameter<tag<1>, int, -1>
> pack;
typedef typename get_param<tag<4> , pack>::type param;
std::cout << param::value << 'n';
return 0;
}
输出:
42
由 GCC 4.6 编译
已编辑以允许修改运行时值:
对于值的运行时修改,只需将参数类修改为以下内容:
template<typename KEY, typename VALUE>
class parameter
{
public:
typedef KEY key_type;
typedef VALUE value_type;
static VALUE value;
};
template<typename KEY, typename VALUE>
VALUE parameter<KEY, VALUE>::value;
它不再具有常量值成员。
请注意,该值是一个静态变量 tough,这意味着使用特定键更改一个条目的值会更改所有其他条目的值。为了克服这个问题,可以简单地修改"标记系统",以便将不同类型的两个标签视为相同的键,然后允许用户指定get_param应该使用哪个元函数来直接识别所需的键(而不是总是使用 std::is_same(。因此,下面提供了现在允许运行时修改值的完整示例:
#include <iostream>
#include <utility>
class nill
{
};
template<typename KEY, typename VALUE>
class parameter
{
public:
typedef KEY key_type;
typedef VALUE value_type;
static VALUE value;
};
template<typename KEY, typename VALUE>
VALUE parameter<KEY, VALUE>::value;
template<typename ...>
class parameter_pack
{
};
template<template<typename> class MF, typename P>
class get_param;
template<template<typename> class MF, typename H, typename ...TAIL>
class get_param<MF, parameter_pack<H, TAIL...>>
{
private:
typedef typename get_param<MF, H>::type result;
public:
typedef typename std::conditional<std::is_same<result, nill>::value,
typename get_param<MF, parameter_pack<TAIL...>>::type, result>::type
type;
};
template<template<typename> class MF>
class get_param<MF, parameter_pack<>>
{
public:
typedef nill type;
};
template<template<typename> class MF, typename K, typename V>
class get_param<MF, parameter<K, V>>
{
public:
typedef typename std::conditional<MF<K>::value,
parameter<K, V> , nill>::type type;
};
template<unsigned T, unsigned U = 0>
class tag
{
};
template<typename K1, typename K2>
class compare_tag;
template<unsigned T1, unsigned U1, unsigned T2, unsigned U2>
class compare_tag<tag<T1, U1>, tag<T2, U2>>
{
public:
static constexpr bool value = T1 == T2;
};
template<typename T>
class find4 : public compare_tag<T, tag<4>>
{};
template<typename T>
class find2 : public compare_tag<T, tag<2>>
{};
template<typename T>
class find1 : public compare_tag<T, tag<1>>
{};
int main()
{
typedef parameter_pack
<
parameter_pack
<
parameter<tag<0, 0>, int>
>,
parameter_pack
<
parameter<tag<4, 0>, int>,
parameter<tag<2, 0>, int>,
parameter_pack
<
parameter<tag<3, 0>, int>,
parameter<tag<4, 1>, int>,
parameter<tag<0, 1>, int>,
parameter<tag<2, 1>, int>
>
>,
parameter<tag<1, 0>, int>
> pack;
std::cin >> get_param<find4, pack>::type::value;
std::cin >> get_param<find2, pack>::type::value;
std::cin >> get_param<find1, pack>::type::value;
std::cout << get_param<find4, pack>::type::value << 'n';
std::cout << get_param<find2, pack>::type::value << 'n';
std::cout << get_param<find1, pack>::type::value << 'n';
return 0;
}
输出:
42
666
0
42
666
0
这就是我目前所拥有的。我可以找到合适的parameter
,我可以手动std::get
的方式,但似乎在这个时候我无法编写最终的包装器,自动为我做一辈子。
一个合适的解决方案应该使用Boost.MPL,以免重新发明常用技术(例如序列和push_back
(。它还可以从一些惰性实例化中受益,因为现在我的解决方案涉及每个节点。
- 提升图:当我的图使用 listS 作为 VertexList 时,如何调用深度优先搜索()?
- 使用迭代深度优先搜索算法的未加权图的最短路径
- 使用后序遍历递归的深度优先搜索会产生意外输出
- 图上的深度优先搜索算法中的内存泄漏
- 为什么此函数中的运行时错误 C++ 深度优先搜索
- 通过深度优先搜索节点链接到自身进行倾倒.C++
- 矢量迭代器在尝试对图形进行深度优先搜索时导致分割错误 11
- 显示深度优先搜索图遍历C++
- 在C++中实现深度优先搜索
- 深度优先搜索过早终止
- 深度优先搜索树遍历实现在C++
- 使用邻接矩阵进行深度优先搜索
- 深度优先搜索的实施和改进
- 并行深度优先搜索C++
- 在迭代深度优先搜索(DFS)算法中确定堆栈大小
- 为什么我在这里泄漏内存(深度优先搜索)c ++
- Traversal迷宫和深度优先搜索
- 在邻接矩阵上应用广度和深度优先搜索
- 深度优先搜索树边分类
- 参数包模板元编程深度优先搜索