5

boost-mpl を使用してコンパイル時に文字列を連結しようとしていますが、gcc からエラーが発生しています。これがサンプルです-

using namespace boost;
using namespace std;

template<class A>
struct type {};

template<>
struct type<int> {
    typedef mpl::string < 'i' > value;
};

template<>
struct type<char> {
    typedef mpl::string < 'c' > value;
};

struct empty {
};

template<class A, class B, class C, class D>
struct converter;

template<class A, class B = empty, class C = empty, class D = empty>

struct converter {
    typedef mpl::push_back< type<A>::value, converter<B,C,D>::value >::type value ;
};

template<>
struct converter<empty, empty, empty, empty> {
    typedef mpl::string < '\0' > value;
};

だから、私が達成しようとしているのは:

converter<int,char,int> == "ici\0" // true. 

問題は、gcc の上記のコードが次のエラーをスローすることです。

main.cpp:37: error: type/value mismatch at argument 1 in template parameter list for ‘template<class Sequence, class T> struct boost::mpl::push_back’
main.cpp:37: error:   expected a type, got ‘type::value’
main.cpp:37: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Sequence, class T> struct boost::mpl::push_back’
main.cpp:37: error:   expected a type, got ‘converter::value’

誰かが上記のコードの問題を指摘し、それを行う正しい方法を説明できますか? ありがとう

EDIT 1: フォーマットの修正といくつかのタイプミス

EDIT 2: Lambdageekの後、Andyの提案により、コードはコンパイルされますが、結果を印刷しようとすると

int main(int argc, char** argv) {
    cout << mpl::c_str< converter<int,char>::value >::value << endl;
    return 0;
}

、コンパイラが不平を言う -

/usr/local/include/boost/mpl/string.hpp:534:   instantiated from ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’
main.cpp:49:   instantiated from here

/usr/local/include/boost/mpl/string.hpp:228: error: ‘value’ is not a member of ‘boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> >’

/usr/local/include/boost/mpl/string.hpp: In instantiation of ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’:
main.cpp:49:   instantiated from here
/usr/local/include/boost/mpl/string.hpp:548: error: no type named ‘value_type’ in struct boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > >’
main.cpp: In function ‘int main(int, char**)’:
main.cpp:49: error: ‘value’ is not a member of ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’
make[2]: *** [build/Debug/GNU-Linux-x86/main.o] Error 1
make[1]: *** [.build-conf] Error 2

私はテンプレート プログラミングに非常に慣れていないことを認めているので、問題は初歩的なものに違いないと確信しています。助けてくれてありがとう

編集 3: コンバータ構造体の push_back 行を変更しました。

エラー:

main.cpp:41: error: type ‘boost::mpl::push_back<typename type<A>::value, typename converter<B, C, D, empty>::value>’ is not derived from type ‘converter<A, B, C, D>’
main.cpp:41: error: expected ‘;’ before ‘value’
4

3 に答える 3

4

OK、最終編集によると、ここにはいくつかの問題があります。

まず、 を使用mpl::push_backして要素をシーケンスに追加できます。これで、2 つのシーケンスが連結されます。の型を に変更しtype<>::value、引数mpl::char_の順序を変更しました(最初にシーケンス、次に要素)。mpl::push_backまた、このコードpush_frontではなく、 を使用する必要があります。push_back最後に、ここで実際の型を抽出する必要があるため、 の::type後に を追加しました。push_front参照用のコードは次のとおりです。

using namespace boost;
using namespace std;

template<class A>
struct type {};

template<>
struct type<int> {
    typedef mpl::char_ < 'i' > value;
};

template<>
struct type<char> {
    typedef mpl::char_ < 'c' > value;
};

struct empty {
};

template<class A, class B, class C, class D>
struct converter;


template<class A, class B = empty, class C = empty, class D = empty>
struct converter {
        typedef typename mpl::push_front< typename converter<B,C,D>::value, typename type<A>::value >::type value ;
};


template<>
struct converter<empty, empty, empty, empty> {
    typedef mpl::string < '\0' > value;
};

これで、このコードは期待どおりに機能します。

int
main (void)
{
        cout << mpl::c_str< converter<int,char>::value >::value << endl;
        return 0;
}

(プリントic)。

于 2011-05-17T22:15:32.483 に答える
2

キーワードを追加して、それが型typenameであることをコンパイラに伝えるのに役立ち::valueますか?

struct converter {
    typedef mpl::push_back< typename type<A>::value, typename converter<B,C,D>::value > value ;
};
于 2011-05-17T21:07:03.590 に答える
2

typename次のキーワードを使用する必要があります。

typedef mpl::push_back< typename type<A>::value, typename converter<B,C,D>>:value >::type value;

テンプレート引数でインスタンス化されたテンプレートのネストされた typedef にアクセスする場合、ネストされた名前がメソッド/フィールドを参照しているか、ネストされた型定義を参照しているかを C++ が判断できるようにする必要があります。何も言わなければ、C++ はそれがフィールド名であると想定します。あなたが言うならtypename、ネストされたものは型であると仮定します。

于 2011-05-17T21:08:49.437 に答える