Создание шаблона шаблона квалифицированного друга - PullRequest
0 голосов
/ 05 января 2019

Глядя на Шаблоны C ++: Полное руководство (2-е издание) / официальный сайт (что в целом великолепно) Сегодня утром я натолкнулся на раздел, который мне не совсем понятен из (12.5.2, если у вас есть книга). Пропустив то, что кажется здесь неактуальным:

Если имя [в объявлении друга] не сопровождается угловыми скобками, есть две возможности

  1. Если имя не определено [...]

  2. Если имя квалифицировано (оно содержит ::), имя должно ссылаться на ранее объявленную функцию или шаблон функции. Функция соответствия предпочтительнее шаблона соответствия функции. Однако такое заявление друга не может быть определением.

со следующим кодом

void multiply(void*);

template <typename T>
void multiply(T);

class Comrades {
    // ... skipping some friends that do not effect the error message
    friend void ::multiply(int); // refers to an instance of the template
    // ...
};

gcc error:

error: ‘void multiply(int)’ should have been declared inside ‘::’
     friend void ::multiply(int);
                               ^

лязг ошибки:

error: out-of-line declaration of 'multiply' does not match any
  declaration in the global namespace
friend void ::multiply(int);
              ^~~~~~~~

Я пытаюсь докопаться до сути, и я несколько раз набрал код (хотя, если у кого-то есть книга ...). Правильно ли правило, а компиляторы не правы? Код не является правильной демонстрацией правила?

Полный код включает более раннее определение функции друга:

class Comrades {
    friend void multiply(int) { }
    friend void ::multiply(int);
}

Какой кланг принимает и отклоняет gcc (это другой вопрос ). В любом случае это не демонстрирует правило, которое заявляет автор, это второе, ссылающееся на предыдущее в том же классе.

1 Ответ

0 голосов
/ 06 января 2019

Книга верна. [temp.friend] p1 - с выделенной соответствующей частью:

Для объявления функции друга, которое не является объявлением шаблона:

  • если имя друга является квалифицированным или неквалифицированным template-id , [...]

  • , если имя друга - квалифицированный идентификатор , и в указанном классе или пространстве имен найдена соответствующая не шаблонная функция, [...]

  • , если имя друга является квалифицированным идентификатором , и в указанном классе или пространстве имен найден соответствующий шаблон функции, объявление друга относится к выводимой специализации этого шаблон функции

  • [...]

...