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

120
12 января 2021, 19:30

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

#include <iostream>
using namespace std;
struct a
{
    friend void operator+(const a&, int)
    {
        cout << "ddd";
    }
} A;
template <class T>
struct c
{
    operator a&() const noexcept
    {
        return A;
    }
    operator a() const noexcept
    {
        return A;
    }
};

int main()
{
    c<a> C{};
    C + 1;
    return 0;
}
Answer 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 (и от шаблонности) сразу исчезнет и код будет компилироваться.

READ ALSO
Указать ID в JQuery

Указать ID в JQuery

Есть счётчик и JS-код, в строке 71 decimals: 0 будет заменяться на 1 или 2Где и как указать ID (например, #%id%), чтобы при нескольких счётчиках на странице,...

111
Как скрыть элементы у родителей с jquery?

Как скрыть элементы у родителей с jquery?

не пойму как скрыть "del" только у тех элементов у которых есть дочерние https://jsfiddlenet/KLON/2z7xpqrt/10/

141
Не добавляется 0 в jquery.mask

Не добавляется 0 в jquery.mask

Хочу сделать маску ( https://githubcom/igorescobar/jQuery-Mask-Plugin ) для номера телефона, чтобы всегда в поле было +70 а дальше уже пользователь мог ввести любые...

125
Динамическое добавление значения в input text

Динамическое добавление значения в input text

Нужно динамически (id будут подставляться автоматически) при клике добавлять значения input в другой inputКак это сделать? Сейчас добавляет только...

113