Конфликт имен между структурой шаблона и функцией-членом шаблона

Далее 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 это ссылка … И все это для простого вызова функции.

7

Решение

Я немного подумал над этим и не могу найти способа заставить работать базовый синтаксис, который вам нужен, из-за всех задействованных шаблонов. Причину, которую вы должны указать 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>();
}

Наконец, если бы вы могли немного подробнее рассказать о реальной проблеме, которую вы пытаетесь решить с помощью этого шаблона, мы могли бы предложить ортогональное решение, которое вообще не предполагает такого псевдонима.

1

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

РЕДАКТИРОВАТЬ: Как указано 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
0

Вы также можете использовать пространство имен.

Поместите «имя структуры» в пространство имен, а затем обратитесь к имени структуры как NS :: name.

namespace NS
{
template<typename T>
struct name {};
}

Вы можете использовать свое оригинальное имя x.template () с таким методом.

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