C++ 参数包模板元编程深度优先搜索

C++ 参数包模板元编程深度优先搜索,c++,c++11,template-meta-programming,C++,C++11,Template Meta Programming,我有这样一个参数类: template <class KEY, class VALUE> class parameter { VALUE v; ... }; 它对第一个参数执行深度优先遍历,该参数具有键值并返回其值。当然,这应该在编译时完成,并且应该具有恒定的运行时。注意KEY这里只是一个空类,它从未被创建或使用过 我希望能从左边或右边做这个 其思想是您可以拥有一组默认参数,您可以将这些参数保存到变量并在将其传递给函数之前进行重写。我认为boost::parameter

我有这样一个参数类:

template <class KEY, class VALUE>
class parameter
{
   VALUE v;
   ...
};
它对第一个
参数执行深度优先遍历,该参数具有
值并返回其值。当然,这应该在编译时完成,并且应该具有恒定的运行时。注意
KEY
这里只是一个空类,它从未被创建或使用过

我希望能从左边或右边做这个

其思想是您可以拥有一组默认参数,您可以将这些参数保存到变量并在将其传递给函数之前进行重写。我认为boost::parameter不允许保存(由于引用了临时参数),我相信当您在一个参数上加倍时,它会给出错误。

是我到目前为止所拥有的。我可以找到合适的
参数
,我可以手动
std::get
找到它,但似乎在这个时候,我无法编写最终的包装器,自动为我完成我的一生


一个合适的解决方案可能应该使用Boost.MPL,以避免重新发明常见的技术(例如,序列&
推回
)。它还可以从一些懒惰的实例化中获益,因为现在我的解决方案涉及到每个节点。

我可能弄错了,但它是否与您正在寻找的下面的代码类似

#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;
}
由GCC4.6编译

编辑以允许修改运行时值: 对于值的运行时修改,只需将参数类修改为以下内容:

template <class KEY_TO_GET, class PARAMETER_PACK>
... get_value(const PARAMETER_PACK& p) { ... }
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;

先生,你真是疯了——
double***
;-)祝你好运@Kerrek嗯,我需要一种不同于
double
的类型,所以我自然使用
double*
。您可以看到它是如何从那里开始的。这看起来非常接近我想要的,但是这些值应该可以在运行时设置,而不仅仅是在编译时。
42
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;
#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