boost — C ++ Невозможно вызвать метод базового класса из производного класса

это мой первый вопрос, надеюсь, я все делаю правильно.

Я пытаюсь извлечь класс из буст-кортежа. Кортежи Boost предоставляют метод-шаблон get () для доступа к отдельным полям. Интересно, что я не могу использовать метод из производного класса.

Следующий код показывает проблему:

#include <iostream>
#include <boost/tuple/tuple.hpp>
using namespace std;

template<typename A>
class Derived : public boost::tuple<A>
{
public:
Derived() : boost::tuple<A>() {}

A& getVal0()
{
return get<0>();
// does not compile:
//error: 'get' was not declared in this scope

return boost::tuple<A>::get<0>();
// does not compile
//error: expected primary-expression before ')' token

return boost::tuples::get<0>(*this);
//works
}
};

int main() {
Derived<int> a;

a.get<0>() = 5;

cout << a.get<0>() << endl;
cout << a.getVal0() << endl;
return 0;
}

Интересно, почему я могу получить доступ к get<0>() метод из основной функции

a.get<0>() = 5;

но не изнутри A& getVal0() метод:

error: 'get' was not declared in this scope

Вторая строка возврата была моей попыткой охватить вызов метода базовым классом:

return boost::tuple<A>::get<0>();

И это порождает другую ошибку

error: expected primary-expression before ')' token

Вызов внешней функции `boost :: tuples :: get<0> (* это) работает. И этот обходной путь мне подходит. Но я все еще задаюсь вопросом, почему я не могу использовать метод кортежа в этой точке.

В документации по бусту есть уведомление для Visual C ++

Заметка! Функции get члена не поддерживаются компилятором MS Visual C ++. Кроме того, у компилятора возникают проблемы с поиском функций get, не являющихся членами, без явного спецификатора пространства имен. Следовательно, все вызовы get должны быть квалифицированы как: tuples :: get (a_tuple) при написании кода, который должен компилироваться с MSVC ++ 6.0.

Но я использую GCC 4.5.2 & 4.8.1

заранее спасибо

6

Решение

Предполагая, что есть get<I>() шаблон функции-члена в базовом классе, вы, вероятно, хотите использовать

this->template get<0>()

this часть необходима для того, чтобы сделать ее зависимым поиском (вы также можете использовать правильную квалификацию класса, но это немного больно и не нужно, если вы не скрываете имя базового класса). template часть надо сказать компилятору, что зависимое имя (get) бывает шаблон.

Основная причина, почему this (или какая-то другая квалификация) и template Нужна двухфазная модель компиляции для шаблонов:

  • Любое имя, которое не зависит напрямую от аргумента шаблона в какой-либо форме, ищется только во время фазы I, то есть в контексте, где шаблон определен. Поскольку аргумент шаблона неизвестен и, следовательно, точная структура базового класса неизвестна (может быть специализированной), любое имя в базовом классе игнорируется. Использование любой квалификации, вызывающей зависимость имени от аргумента шаблона, например использование this->перемещает поиск в фазу II, то есть когда создается экземпляр шаблона.
  • Если имя является зависимым, возникает двусмысленность, если выражение включает в себя < символ, в то время как шаблон анализируется на этапе I, т.е. когда аргументы шаблона еще не известны: < может быть либо началом явного аргумента шаблона для вызова функции-члена, либо это может быть оператор меньше чем. Поскольку явное упоминание аргументов шаблона встречается редко (ну, по крайней мере, это было редко, когда были сделаны эти правила), предполагается, что по умолчанию это оператор меньше чем. Чтобы указать, что имя на самом деле является шаблоном функции-члена с явно заданным аргументом шаблона, ему должно предшествовать ключевое слово template (очень похоже на типы, нуждающиеся в typename).
5

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

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

По вопросам рекламы [email protected]