Функция шаблона не работает после компиляции с C ++ 11 - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть очень простая шаблонная функция для сравнения поля rank с двумя structs:

template<typename T>
bool comp_rank(const T &a, const T &b){
    return a.rank < b.rank;
}

Это работало нормально, пока я не скомпилировал с -std=c++11.Теперь я получаю ошибку

error: parameter "b" is not a type name
      return a.rank < b.rank;
                      ^

./src/util.h(123): error: expected a ">"
      return a.rank < b.rank;
                       ^

Что дает?Похоже, что основной синтаксис, который я бы удивился, изменился после C ++ 11.

Ответы [ 3 ]

0 голосов
/ 10 декабря 2018

Редактировать : Я отправил отчет об ошибке в gcc здесь .В настоящее время он не подтвержден.

Учитывая, что вы приняли @ ответ Клауса , ваш код выглядит примерно как (спасибо @krzaq):

#include <type_traits>

using namespace std;

struct A{ int rank; };

template<typename T>
bool comp_rank(const T &a, const T &b){
    return a.rank < b.rank;
}

int main()
{
    A a{42}, b{0};
    comp_rank(a, b);
}

И gcc (9.0.0 и более ранние версии были протестированы), и clang (8.0.0 и более ранние версии были протестированы) отклоняют этот код на том основании, что они ожидают, что id-expression a.rank< будет началом шаблона.Согласно стандарту, это неверное толкование.См. [Basic.lookup.classref]

В выражении доступа к члену класса, если сразу за маркером . или -> следует идентификатор, за которым следует <, Идентификатор необходимо найти, чтобы определить, является ли < началом списка аргументов шаблона или оператором «меньше».Идентификатор сначала ищется в классе выражения объекта.Если идентификатор не найден, он затем просматривается в контексте всего postfix-выражения и должен называть шаблон класса.

Компилятор должен иметь посмотрел a.rank и обнаружил, что это целочисленный член класса A. MSVC 19.00.23506 компилирует это просто отлично

0 голосов
/ 11 декабря 2018

Это проблема, с которой CGW 1835 имеет дело, цитируя ее здесь:

Согласно пункту 6.4.5 [basic.lookup.classref]

В выражении доступа к члену класса (8.2.5 [expr.ref]), если.или -> за маркером сразу же следует идентификатор, за которым следует <, идентификатор необходимо найти, чтобы определить, является ли <начало списка аргументов шаблона (17.2 [temp.names]) или оператор меньше чем.Идентификатор сначала ищется в классе выражения объекта.Если идентификатор не найден, он затем просматривается в контексте всего выражения postfix и должен называть шаблон класса. </p>

template<typename T> T end(T);
template<typename T>
bool Foo(T it) {
    return it->end < it->end;
}

, поскольку он является зависимым и, следовательно, конец не может быть просмотренвверх в классе выражения объекта, это ищется в контексте выражения postfix.Этот поиск находит шаблон функции, делая выражение неправильно сформированным.

Одной из возможностей может быть ограничение поиска классом выражения объекта, когда выражение объекта является зависимым.


#include <type_traits>

using namespace std;

template<typename T>
bool comp_rank(const T &a, const T &b){
    return a.rank < b.rank; // fail
}

Ошибка обнаруживается даже без создания экземпляра шаблона функции, все выражение является зависимым, поэтому их нельзя найти в области видимости класса.Поскольку текущая формулировка стандарта не ясна, если поиск для rank в области видимости класса будет отложен для зависимых имен или должен быть связан с именами в контексте выражения postfix , это то, что CGWпопробуйте заняться.

прямое решение - использовать паренс:

template<typename T>
bool comp_rank(const T &a, const T &b){
    return (a.rank) < (b.rank);
}
0 голосов
/ 10 декабря 2018

Ваша проблема в том, что вы используете

using namespace std;

Поскольку c ++ 11 представляет шаблон rank

См. Здесь: https://en.cppreference.com/w/cpp/types/rank

Если вы удалитеоператор using, все снова прекрасно компилируется!

Вот сообщение об ошибке, выданное gcc 8.2.1

main.cpp: In function 'bool comp_rank(const T&, const T&)':
main.cpp:41:23: error: type/value mismatch at argument 1 in template parameter list for 'template<class> struct std::rank'
    return a.rank < b.rank;

В любом случае не рекомендуется использовать using namespace ....Вы уже привели хороший пример;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...