Далее GCC путает структуру шаблона name
с функцией-членом шаблона name
класса A
пока Clang компилирует нормально (живой пример):
template<typename T>
struct name {};
struct A
{
template<bool B>
void name() { }
};
template<bool B, typename T>
void f(T& x) { x.template name<B>(); }
функция f
по-видимому, вызывается с аргументом типа A
в этом примере, но это может быть что-нибудь еще, так f
должен оставаться функцией шаблона.
Меня не волнует, какой компилятор правильный, мне нужен только обходной путь, потому что я действительно не знаю никакого синтаксиса, кроме
x.template name<B>();
вызвать функцию-член, и я не могу понять, как using
Декларация или любой другой способ устранения неоднозначности может применяться.
РЕДАКТИРОВАТЬ Да, я сейчас попробовал более явный синтаксис
x.T::template name<B>();
который работает, но действительно уродливо. Есть ли способ заставить работать короткий синтаксис? В противном случае, может быть предпочтительнее изменить одно из двух имен для начала …
EDIT2 Моя оригинальная версия f
работает по универсальной ссылке T&&
, который нуждается в уродливый
using X = typename std::remove_reference<T>::type;
x.X::template name<B>();
в случае T
это ссылка … И все это для простого вызова функции.
Я немного подумал над этим и не могу найти способа заставить работать базовый синтаксис, который вам нужен, из-за всех задействованных шаблонов. Причину, которую вы должны указать template
потому что в противном случае он выглядит на компилятор, как вы используете <
сравнить адрес функции с B
,
Как вы сказали, вы можете просто переименовать один из name
идентификаторы, позволяющие компилятору не иметь двусмысленности относительно того, что вы имеете в виду.
С другой стороны, вы можете сделать именно то, что вы сказали, и полностью квалифицировать вызов. Я не считаю это уродливым синтаксисом: он совершенно понятен читателю именно так что происходит, и в конце концов вам нужно написать функцию только один раз.
template<bool B, typename T>
void f(T& x)
{
typedef typename std::remove_reference<T>::type callee;
x.callee::template name<B>();
}
Наконец, если бы вы могли немного подробнее рассказать о реальной проблеме, которую вы пытаетесь решить с помощью этого шаблона, мы могли бы предложить ортогональное решение, которое вообще не предполагает такого псевдонима.
РЕДАКТИРОВАТЬ: Как указано Constructor и iavr, следующее является нестандартным поведением:
С VS2013 работает следующее:
template<typename T>
struct name {};
struct A
{
template<bool B>
void name() {
std::cout << "A::name() called with B=" << B<< std::endl;
}
};
template<bool B, typename T>
void f(T& x) { x.name<B>(); }
int main(){
A a;
f<true>(a);
}
выход:
A::name() called with B=1
Вы также можете использовать пространство имен.
Поместите «имя структуры» в пространство имен, а затем обратитесь к имени структуры как NS :: name.
namespace NS
{
template<typename T>
struct name {};
}
Вы можете использовать свое оригинальное имя x.template () с таким методом.