Подтвердить что ты не робот

Неоднозначная перегрузка оператора на clang

Когда я пытаюсь скомпилировать эту тестовую программу:

struct comma_guard
{
    template<class T>
    const comma_guard& operator,(T&&) const
    {
        return *this;
    }
};

struct foo {};
template<class T> T operator,(T x, foo)
{
    return x;
}

int main()
{
    (comma_guard(), foo());
}

Я получаю ошибку компиляции clang:

comma_guard.cpp:20:19: error: use of overloaded operator ',' is ambiguous (with operand types 'comma_guard' and 'foo')
    (comma_guard(), foo());
     ~~~~~~~~~~~~~^ ~~~~~
comma_guard.cpp:6:24: note: candidate function [with T = foo]
    const comma_guard& operator,(T&&) const
                       ^
comma_guard.cpp:13:21: note: candidate function [with T = comma_guard]
template<class T> T operator,(T x, foo)
                    ^

Это компилирует штраф на gcc. Из моего понимания поиска ADL функция-член в comma_guard должна быть предпочтительной и поэтому не должна быть двусмысленной. Это верно? Это ошибка в clang? Кроме того, существует ли временное решение, чтобы оператор в comma_guard всегда был предпочтительнее?

Обновление. Таким образом, кажется, что clang не считает его членом класса при его шаблоне. Поэтому, если я определяю comma_guard следующим образом, он будет работать:

struct comma_guard
{
    struct any
    {
        template<class T>
        any(T&&);
    };
    const comma_guard& operator,(any) const;
};

Что правильно в соответствии с С++?

4b9b3361

Ответ 1

Из моего понимания поиска ADL функция-член в comma_guard должна быть предпочтительной и поэтому не должна быть двусмысленной. Правильно ли это?


Ответ: Во время разрешения перегрузки и согласно стандарту § 13.3.1/2 и 7 Функции кандидата и списки аргументов [over.match.funcs]:

2 Набор функций-кандидатов может содержать как функции-члены, так и не-члены, которые должны быть разрешены в отношении одного и того же списка аргументов.

7 В каждом случае, когда кандидат является шаблоном функции, специализированные шаблоны функций кандидата генерируются с использованием вычитания аргумента шаблона (14.8.3, 14.8.2). Затем эти кандидаты обрабатываются как функции кандидата обычным способом [126].

[footnote 126] Процесс вывода аргумента полностью определяет типы параметров специализированных шаблонов, т.е. параметры специализированных шаблонов шаблонов не содержат типов параметров шаблона. Следовательно, за исключением тех случаев, в противном случае функции шаблонов функций и функции без шаблона (8.3.5) обрабатываются эквивалентно для остальной части разрешения перегрузки.

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

Даже если он имел GCC, выбирает бесплатный шаблонный перегруженный оператор LIVE DEMO.

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


Кроме того, есть ли способ обхода, чтобы оператор в команде comma_guard всегда был предпочтительнее?


Ответ: Да хотя и довольно уродливый: (comma_guard().operator,(foo())); LIVE DEMO