"Странная" ссылка на функцию-член c должна вызываться "ошибка - PullRequest
0 голосов
/ 13 апреля 2020

Почему я получаю сообщение об ошибке "ссылка на нестати c должна вызываться функция-член":

<source>:35:19: error: reference to non-static member function must be called

    list_.front().Set<Flags::First>(true);

    ~~~~~~~~~~~~~~^~~

<source>:40:10: note: in instantiation of member function 'List<int>::Set' requested here

    list.Set();

         ^

<source>:13:8: note: possible target for call

  void Set(bool value) {

       ^

1 error generated.

Compiler returned: 1

, когда я пытаюсь скомпилировать этот код с помощью clang 7.0.0?

#include <iostream>
#include <list>
using namespace std;

enum class Flags : uint8_t {
    First  = 1,
    Second = 2
};

class Header {
public:
  template <Flags flag>
  void Set(bool value) {
       flags_ = static_cast<Flags>(
           value
           ? (static_cast<uint8_t>(flags_) | static_cast<uint8_t>(flag))
           : (static_cast<uint8_t>(flags_) & (~static_cast<uint8_t>(flag))));
  }

private:
  Flags flags_{};
};

template <class T>
class List {
public:
    void Set();

private:
    std::list<Header> list_;
};

template <class T>
void List<T>::Set() {
    list_.front().Set<Flags::First>(true);
}

int main() {
    List<int> list;
    list.Set();
    return 0;
}

Смотрите здесь: https://godbolt.org/z/KXttBb

1 Ответ

2 голосов
/ 13 апреля 2020

Мы можем разбить как то, как диагностировать это, так и как и почему исправление работает.

<source>:35:19: error: reference to non-static member function must be called

ОК, поэтому clang думает, что что-то называет нестатичную c функцию-член, и что выражение, в котором вы его используете, является , а не вызовом функции:

list_.front().Set<Flags::First>(true);

~~~~~~~~~~~~~~^~~

Это довольно ясно говорит нам о том, что он распознает Set как функцию, не являющуюся членом c , но считает, что Set<Flags::First>(true) является , а не вызовом функции.

Очевидно, что это именно правильный синтаксис для вызова шаблона функции, поэтому проблема заключается в том, что clang не рассматривает Set как шаблон функции.


На этом этапе обязательно прочитайте вопрос, указанный в комментариях выше, и принятый ответ .

...


Хорошо, теперь вы прочитали это, очевидно, что Set является зависимым именем функции, и мы можем решить проблему, добавив template следующим образом:

list_.front().template Set<Flags::First>(true);

но это все еще оставляет открытым вопрос почему имя зависимый. Я имею в виду, читая код, мы знаем, что list_.front() должен иметь тип Header&, верно?

Итак, давайте попробуем написать это явно:

Header &front = list_.front();
front.Set<Flags::First>(true);

и мы увидим (все еще с лязгом 8 или 9), что теперь это работает без дополнительных template. Если вы напишите auto &front, проблема вернется.

FWIW, это отображается в clang 8 и 9, но исчезает в clang 10 и, кажется, никогда не возникает в G CC. Таким образом, это может быть ошибка, но, по крайней мере, теперь вы знаете, как ее диагностировать и как ее обойти.

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