1

私は次のようなパラメータクラスを持っています:

template <class KEY, class VALUE>
class parameter
{
   VALUE v;
   ...
};

そして、私はパラメータパッククラスを持っています:

template <class... ELEMENTS>
class parameter_pack 
{
  std::tuple<ELEMENTS...> elems;
};

parameter_packsparametersおよび/またはの数が含まれていますparameter_packs

次のような関数 (またはメソッド) が必要です。

template <class KEY_TO_GET, class PARAMETER_PACK>
... get_value(const PARAMETER_PACK& p) { ... }

parameter値を持ち、KEYその値を返す最初のものに対して深さ優先トラバーサルを行います。もちろん、これはコンパイル時に実行する必要があり、一定の実行時間を持つ必要があります。KEYこれは単なる空のクラスであり、作成も使用もされないことに注意してください。

これを左からでも右からでもできるようにしたいです。

アイデアは、変数に保存して関数に渡す前にオーバーライドできる一連のデフォルトパラメーターを持つことができるということです。boost::parameter は保存を許可しないと思います(一時変数への参照のため)。パラメーターを2倍にするとエラーが発生すると思います。

4

2 に答える 2

2

私はそれを間違っているかもしれませんが、あなたが探している以下のコードに似たものではありませんか?

#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;

もう定数値メンバーはありません。

値はタフな静的変数であることに注意してください。つまり、特定のキーで 1 つのエントリの値を変更すると、他のすべてのエントリの値が変更されます。この問題を克服するには、単に「タグ付けシステム」を変更して、異なるタイプの 2 つのタグが同じキーと見なされるようにし、ユーザーが必要なキーを正しく識別するために 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
于 2011-06-22T12:49:32.967 に答える
0

これは私がこれまでに持っているものです。私は適切な を見つけることがparameterできstd::get、手でそれを見つけることができますが、現時点では、私の人生のために自動的にそれを行う最終的なラッパーを書くことができないようです.

一般的な手法 (例: シーケンス & ) を再発明しないように、適切な解決策はおそらく Boost.MPL を使用する必要がありますpush_back。現在、私のソリューションはすべてのノードに触れるため、遅延インスタンス化の恩恵を受けることもできます。

于 2011-06-09T08:46:31.913 に答える