0

考慮してください (リンク):

#include <cstdlib>
#include <cassert>

#pragma pack (1)

template <size_t Width>
class Base
{
public:
    char mData [Width];
    template <typename Field> Field ExtractAs () const
    {
        return *reinterpret_cast <Field> (mData);
    }
};

template <typename FieldVal>
class IntegralField
:
    public Base <sizeof (FieldVal)>
{
public:
    FieldVal GetVal () const
    {
        return ExtractAs <FieldVal> ();
    }
};

int main()
{
    char raw[4] = {0x11, 0x22, 0x33, 0x44};
    typedef IntegralField <uint32_t> UInt32Field;
    const UInt32Field& field =
        *reinterpret_cast <const UInt32Field*> (raw);
    const uint32_t extracted = field.GetVal();
    assert (extracted == 0x44332211);
}

呼び出し:

return ExtractAs <FieldVal> ();

g++ 4.7.2 でコンパイルに失敗する:

main.cpp: In member function ‘FieldVal IntegralField<FieldVal>::GetVal() const’:
main.cpp:25:16: error: ‘ExtractAs’ was not declared in this scope
main.cpp:25:35: error: expected primary-expression before ‘&gt;’ token
main.cpp:25:38: error: expected primary-expression before ‘)’ token
main.cpp: In function ‘int main()’:
main.cpp:32:28: error: ‘uint32_t’ was not declared in this scope
main.cpp:32:36: error: template argument 1 is invalid
main.cpp:32:49: error: invalid type in declaration before ‘;’ token
main.cpp:35:11: error: ‘uint32_t’ does not name a type
main.cpp:36:5: error: ‘extracted’ was not declared in this scope
ninja: build stopped: subcommand failed.

using Base::ExtractAstypedefs などを含む多くのトリックを試しましたが、役に立ちませんでした。

私がやろうとしていることは C++03 で可能ですか? 派生クラス テンプレート メンバー関数から基本クラス テンプレートの関数テンプレートを呼び出すにはどうすればよいですか? C++11 は使用できないことに注意してください。

編集:GetVal型についてより明確にするために再定義すると:

  FieldVal GetVal () const
    {
        static const size_t fieldSize = sizeof (FieldVal);
        typedef Base <fieldSize> MyBase;
        typedef FieldVal MyField;
        return MyBase::ExtractAs <MyField> ();
    }

私はまだ得る:

error: expected primary-expression before ‘&gt;’ token

の上:return MyBase::ExtractAs <MyField> ();

編集:これが最終的な作業コードです:

#include <cstdlib>
#include <cassert>
#include <stdint.h>

#pragma pack (1)

template <size_t Width>
class Base
{
public:
    char mData [Width];
    template <typename Field> Field ExtractAs () const
    {
        return *reinterpret_cast <const Field*> (mData);
    }
};

template <typename FieldVal>
class IntegralField
:
    public Base <sizeof (FieldVal)>
{
public:
    FieldVal GetVal () const
    {
        return this->template ExtractAs<FieldVal>();
    }
};

int main()
{
    char raw[4] = {0x11, 0x22, 0x33, 0x44};
    typedef IntegralField <uint32_t> UInt32Field;
    const UInt32Field& field =
        *reinterpret_cast <const UInt32Field*> (raw);
    const uint32_t extracted = field.GetVal();
    assert (extracted == 0x44332211);
}
4

1 に答える 1

2

次のように言うことができます。

return this->template ExtractAs<FieldVal>();

または

return Base<sizeof(FieldVal)>::template ExtractAs<FieldVal>();

あなたはクラステンプレートにいて、ベースもテンプレートの特殊化であるため、ベースメンバーの名前は派生テンプレートに自動的に挿入されません。(特化するとどうなるか考えてみてくださいBase!)

名前を修飾するか を使用this->すると、名前全体が依存するようになるため、最初のフェーズでエラーが発生することはありません。また、名前ExtractAsは依存しているため (テンプレートのネストされた名前)、 として明確にする必要がありますtemplate

于 2013-07-05T19:37:38.520 に答える