1

編集:サンプルを編集して、私が抱えている問題によりよく似るようにしました。関数は(テンプレート パラメーターだけでなく)通常のパラメーターに依存するようになりました。これは、コンパイル時に計算を行うことができないことを意味します。


手書きのタイプリストでいくつかのコードを書きましたが、今はブーストmplを使い始めており、それをライブラリに移動しようとしています。

のまともなドキュメントが見つからないようでmpl::list、コードを に移植することさえできていませんboost::mpl。コードの移植に成功したとしても (仮に?)、それは慣用的なものにはならないと感じています。次のコードの書き方を教えてくださいboost(これは実際のコードではなく、わざと単純化したものであることに注意してください)。

元のコード (codepad.org 貼り付け)

class nil {};

template <class Head, class Tail = nil>
struct type_list {
    typedef Head head;
    typedef Tail tail;
};

template <class List>
struct foo;

template <class Head, class Tail>
struct foo<type_list<Head, Tail> >{
    template <class T>
    static void* bar(T* obj, size_t size)
    {
        if (sizeof(Head) == size) 
            return reinterpret_cast<Head*>(obj);

        // Otherwise check the rest of the list
        return foo<Tail>::bar(obj, size);
    }
};


template <>
struct foo<nil>
{
    template <class T>
    static void* bar(T*, size_t)  { return NULL; }
};

#include <iostream>

int main()
{
    int n = 3;
    void *p = foo<type_list<char, type_list<bool, 
                      type_list<double, type_list<long> > > >
                 >::bar(&n, 4); 
    std::cout<< p << std::endl;
}

Boost の使用に失敗しました (codepad.org の貼り付け)

#include <boost/mpl/list.hpp>

template <class List>
struct foo{
    template <class T>
    static void* bar(T* obj, size_t size)
    {
        typedef typename boost::mpl::front<List>::type type;
        if (sizeof(type) == size) 
            return reinterpret_cast<type*>(obj);

        // Otherwise check the rest of the list
    return foo<typename List::next>::bar(obj, size);
  }
};

template <>
struct foo<boost::mpl::list0<boost::mpl::na> >
{
    template <class T>
    static void* bar(T*)
    {
        return NULL;
    }
};

#include <iostream>

int main()
{
    int n = 3;
    void *p = foo<boost::mpl::list<char, bool, double, long> >::bar(&n, 4);
    std::cout << p << std::endl;
}
4

4 に答える 4

4

MPL は、コンパイル時と実行時の混合操作には適していません。

MPL シーケンスで実行時に許可される唯一の操作は「for_each」です。他のすべての状況では、自分でロールする必要があります。

したがって、MPL 型はインスタンス化することを意図していないことを効果的に考慮する必要があります。

しかし、Boost にはそのような機能が他にもあります。

古い: Boost.Tuple

新しい: Boost.Fusion > http://spirit.sourceforge.net/dl_more/fusion_v2/libs/fusion/doc/html/index.html

Boost.Fusion はもう少し複雑です (たとえば、ビューの概念を統合します) が、あなたの例にははるかに適しています。

MPL を使用してはいけないという意味ではありません。逆に、Boost.Fusion リファレンス ドキュメントでは、コンパイル時の計算に MPL アルゴリズムを使用し、コンパイル時と実行時の境界を越えた瞬間にのみ Boost.Fusion コンテナーをビルドする必要があることが明示的に述べられています (ただし、Boost.Fusion コンテナーは MPL アルゴリズムで動作するはずです)。

そのため、mpl 実装を維持して、結果のリストを Boost.Fusion シーケンスに変換します。次に、シーケンスをインスタンス化し、すべての Boost.Fusion 機能を利用します。

于 2009-07-29T16:34:11.483 に答える
2

boost::mpl::fold次のように使用します。

#include <boost/mpl/list.hpp>
#include <boost/mpl/fold.hpp>

#include <iostream>

using namespace boost::mpl;

// Initial state:
struct foo_start {
    template <typename T>
    static void * bar( T *, size_t ) { return 0; }
};

// Folding Step: add This to Prev
template <typename Prev, typename This>
struct foo_iteration {
    struct type {
        template <typename T>
        static void * bar( T * obj, size_t size ) {
            if ( sizeof(This) == size )
                return reinterpret_cast<This*>(obj);
            else
                return Prev::bar( obj, size );
        }
    };
};

// foo is just calling mpl::fold now:
template <typename List>
struct foo : fold< List, foo_start, foo_iteration<_,_> >::type {};

int main() {
    int n = 3;
    void * p = foo< list<char, bool, double, long> >::bar( &n, 4 );
    std::cout << p << std::endl;
}

0ここに表示されますが、私は amd64 を使用しているため、 を に変更し、ゼロ以外の値を取得する必要があり4ます8

HTH

于 2009-07-26T20:49:07.250 に答える
0

私の理解が正しければ、実行時に T を渡し、{A、B、C、D} の MPL リストがそのセット内の正しい T を選択して動作することを期待していますか?

私は間違っているかもしれませんが、これは Boost.Fusion に適しているように思えます。Boost.Fusion は、コンパイル時のシーケンスの実行時の反復用に設計されています。

于 2009-07-27T13:30:26.600 に答える
0

警告: しばらく C++ (メタ プログラミング) を行っていないので、間違っている可能性があります。

私が正しく理解している場合、元のコードは最初の型を見つけます。これは、渡された引数と同じサイズで、引数をその型にキャストします。それを実装すると、mpl基本的には、型のサイズをテストするカスタム記述述語でfind_ifアルゴリズムを使用することになります (上記のリンクの例を参照してください)。結果だけtypedefをキャストすれば完了です。

于 2009-07-26T20:50:41.727 に答える