это мой первый вопрос, надеюсь, я все делаю правильно.
Я пытаюсь извлечь класс из буст-кортежа. Кортежи 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
заранее спасибо
Предполагая, что есть get<I>()
шаблон функции-члена в базовом классе, вы, вероятно, хотите использовать
this->template get<0>()
this
часть необходима для того, чтобы сделать ее зависимым поиском (вы также можете использовать правильную квалификацию класса, но это немного больно и не нужно, если вы не скрываете имя базового класса). template
часть надо сказать компилятору, что зависимое имя (get
) бывает шаблон.
Основная причина, почему this
(или какая-то другая квалификация) и template
Нужна двухфазная модель компиляции для шаблонов:
this->
перемещает поиск в фазу II, то есть когда создается экземпляр шаблона.<
символ, в то время как шаблон анализируется на этапе I, т.е. когда аргументы шаблона еще не известны: <
может быть либо началом явного аргумента шаблона для вызова функции-члена, либо это может быть оператор меньше чем. Поскольку явное упоминание аргументов шаблона встречается редко (ну, по крайней мере, это было редко, когда были сделаны эти правила), предполагается, что по умолчанию это оператор меньше чем. Чтобы указать, что имя на самом деле является шаблоном функции-члена с явно заданным аргументом шаблона, ему должно предшествовать ключевое слово template
(очень похоже на типы, нуждающиеся в typename
).Других решений пока нет …