60
задан 8 January 2019 в 19:30

1 ответ

Поиск имени должен произойти сначала. В этом случае для имени operator++.

[basic.lookup] (шахта акцента)

1 правила поиска имени применяются однородно ко всем именам (включая имена определения типа ([dcl.typedef]), имена пространства имен ([basic.namespace]) и имена классов ([class.name])) везде, где грамматика позволяет такие имена в контексте, обсужденном конкретным правилом. Поиск имени связывает использование имени с объявлением ([basic.def]) того имени. поиск Имени должен найти однозначное объявление для имени (см. [class.member.lookup]) . Поиск имени может связать больше чем одно объявление с именем, если это находит, что имя имя функции; объявления, как говорят, формируют ряд перегруженных функций ([over.load]). разрешение Перегрузки ([over.match]) происходит после того, как поиск имени успешно выполнился . Правила доступа (Пункт [class.access]) рассматривают только, после того как поиск имени и функциональное разрешение перегрузки (если применимо) успешно выполнились. Только после поиска имени, функциональное разрешение перегрузки (если применимо) и проверка доступа успешно выполнились, атрибуты, представленные объявлением имени, используемым далее в обработке выражения (Пункт [expr]).

И только если поиск однозначен, перегрузится, разрешение продолжаются. В этом случае имя найдено в пределах двух различных классов, и таким образом, неоднозначность присутствует даже до разрешения перегрузки.

[class.member.lookup]

8, Если название перегруженной функции однозначно найдено, перегрузив разрешение ([over.match]) также, происходит перед управлением доступом. Неоднозначности могут часто разрешаться путем квалификации имени с его именем класса. [Пример:

struct A {
  int f();
};

struct B {
  int f();
};

struct C : A, B {
  int f() { return A::f() + B::f(); }
};

— пример конца]

пример в значительной степени суммирует довольно длинные правила поиска в предыдущих абзацах [class.member.lookup]. В Вашем коде существует неоднозначность. GCC корректен для создания отчетов об этом.

<час>

Что касается работы вокруг этого, люди в комментариях уже представили идеи для обходного решения. Добавьте помощника класс

template <class CRTP>
struct PrePost
    : Pre<CRTP>
    , Post<CRTP>
{
    using Pre<CRTP>::operator++;
    using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};

CRTP, которым имя теперь найдено в пределах единого класса и называет обе перегрузки. Поиск успешен, и разрешение перегрузки может продолжиться.

63
ответ дан 1 November 2019 в 10:52

Другие вопросы по тегам:

Похожие вопросы: