& quot; Не объявлено в этой области & quot; ошибка разрешения имени шаблона функции в общедоступном шаблоне базового класса

Рассматривать (ссылка на сайт):

#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 ‘>’ 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::ExtractAs, typedefи т. д., но безрезультатно.

Возможно ли то, что я пытаюсь сделать в 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 ‘>’ 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);
}

0

Решение

Вы можете также сказать:

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

Или же

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

Поскольку вы находитесь в шаблоне класса, а база тоже является специализацией шаблона, имена базовых членов не вводятся автоматически в производный шаблон. (Подумайте, что случится, если вы Base!)

Уточняя имя или используя this->вы делаете все имя зависимым, и это не приводит к ошибке на первом этапе. Кроме того, так как имя ExtractAs является зависимым (будучи вложенным именем шаблона), вы должны устранить его как template,

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector