Страницы

Поиск по вопросам

суббота, 14 декабря 2019 г.

Почему не работает implicit conversion

#cpp


почему код с template компилируется, а без него нет

#include 
using namespace std;

struct a
{
    friend void operator+(const a&, int)
    {
        cout << "ddd";
    }
} A;

template 
struct c
{
    operator a&() const noexcept
    {
        return A;
    }
    operator a() const noexcept
    {
        return A;
    }
};


int main()
{
    c C{};
    C + 1;
    return 0;
}

    


Ответы

Ответ 1



Если функция объявлена только как friend внутри класса, то она формально принадлежит охватывающему пространству имен. Но при этом она не видна обычному процессу поиска имен, а может быть видна лишь ADL-поиску (Argument Dependent Lookup). ADL-поиск делается через ассоциированные пространства имен и ассоциированные классы. Если один из аргументов имеет тип специализированного шаблона, то в список ассоциированных классов будут добавлены все типы аргументов этого шаблона. В вашем примере поиск подходящего оператора + производится в глобальном пространстве имен. Один из аргументов + является специализацией шаблона c с аргументом a. Это приводит к включению a в список ассоциированных классов и к тому, что friend-функции этого класса становится видимыми с точки зрения ADL в глобальном пространстве имен. Если вы уберете шаблонность, то класс a будет совершенно посторонним классом, никак не фигурирующим в выражении C + 1. Он не будет рассматриваться ADL в качестве ассоциированного класса и его friend-функции так и останутся "невидимыми". Если вы дополнительно явно объявите свой оператор в охватывающем пространстве имен struct a { friend void operator+(const a&, int) { cout << "ddd"; } } A; void operator+(const a&, int); тот он будет виден сразу и всегда обычному процессу поиска имен. Зависимость от ADL (и от шаблонности) сразу исчезнет и код будет компилироваться.

Комментариев нет:

Отправить комментарий