Не могу понять прикола
От: K13 http://akvis.com
Дата: 05.03.24 11:20
Оценка:
код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb

каким-то образом при наличии НЕшаблонного operator|() для конкретного enum
он перестает его видеть если в неймспейсе A добавить шаблонный оператор|() который всегда отключен.

Что-то я торможу. Не понимаю, что происходит при смене #if 1 / #if 0
Re: Не могу понять прикола
От: so5team https://stiffstream.com
Дата: 05.03.24 12:05
Оценка:
Здравствуйте, K13, Вы писали:

K13>код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb


А что это у вас за прикол:

template<typename T> std::enable_if_t< false, T >


Это такой способ записать = delete без = delete?
Re: Не могу понять прикола
От: reversecode google
Дата: 05.03.24 12:21
Оценка:
а что будет если добавить такой конструктор)))?
constexpr inline QFlags(int f) noexcept : i(int(f)) {}
Re: Не могу понять прикола
От: so5team https://stiffstream.com
Дата: 05.03.24 12:30
Оценка: 92 (4) +1
Здравствуйте, K13, Вы писали:

K13>код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb


Поскольку никто более знающий не высказывается, то риску предположить, что дело в следующем:

— компилятор пытается найти operator| в пространстве имен Qt и не находит;
— компилятор пытается найти operator| в пространстве имен A и находит, но он запрещен из-за std::enable_if<false, T>;
— после чего компилятор перестает искать operator| для Qt::ItemFlag и делает неявное преобразование Qt::ItemFlag в int, после чего применяет штатный operator| для int-ов.

Если вы свой operator| для Qt::ItemFlag перенесете в пространство имен Qt, то должно все компилироваться даже если в A operator| написан без sfinae: https://coliru.stacked-crooked.com/a/f2b68b55222881d2
Re[2]: Не могу понять прикола
От: reversecode google
Дата: 05.03.24 12:37
Оценка:
и не говорите, никто за 5 минут так и не соизволил))

да понятно что там прыжки по ADL

что любопытно, MSVC до С++17 компилит и не краснеет))
Re: Не могу понять прикола
От: rg45 СССР  
Дата: 05.03.24 14:04
Оценка:
Здравствуйте, K13, Вы писали:

K13>код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb


K13>каким-то образом при наличии НЕшаблонного operator|() для конкретного enum

K13>он перестает его видеть если в неймспейсе A добавить шаблонный оператор|() который всегда отключен.

K13>Что-то я торможу. Не понимаю, что происходит при смене #if 1 / #if 0


А теперь внимательно следим за руками. Але — оп!

https://coliru.stacked-crooked.com/a/2c4e87217e010d24

(Внимание на строчку 49).

Нужно объяснять, или понял уже?

P.S. Так устроен поиск имен — компилер находит в namespace A operator | и на этом путешествие по пространствам имен прекращается. После этого выясняется, что найденный operator | не проходит overload resolution благодаря SFINAE фильтру "std::enable_if_t< false, T >", а других подходящих кандитатов на подстановку в этой области видимости нет. Остается последняя возможность — integral promotion of unscoped enumeration type to int с последующим применением встроенного оператора.

Влепи туда вместо своего operator | какой-нибудь другой, совершенно левый, и получишь ту же самую ошибку:

https://coliru.stacked-crooked.com/a/72f49a4ac048faed

namespace A {

#if 1 // если тут поставить 0 то все компилируется

//using ::operator|;

auto operator | (class Absent&, class Absent&);

#endif
} // namespace A
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.03.2024 16:15 rg45 . Предыдущая версия . Еще …
Отредактировано 05.03.2024 15:58 rg45 . Предыдущая версия .
Отредактировано 05.03.2024 15:04 rg45 . Предыдущая версия .
Отредактировано 05.03.2024 14:22 rg45 . Предыдущая версия .
Отредактировано 05.03.2024 14:13 rg45 . Предыдущая версия .
Отредактировано 05.03.2024 14:12 rg45 . Предыдущая версия .
Re[3]: Не могу понять прикола
От: rg45 СССР  
Дата: 05.03.24 14:07
Оценка:
Здравствуйте, reversecode, Вы писали:

R>что любопытно, MSVC до С++17 компилит и не краснеет))


А ты в режиме "/permissive-" попробуй

Он же потому и не краснеет, что до C++17 (включительно) режим по умолчанию — просто "/permissive", а вот начиная с C++20, по умолчанию используется "/permissive-". Но режимы можно попереключать и вручную.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.03.2024 14:16 rg45 . Предыдущая версия .
Re: Не могу понять прикола
От: rg45 СССР  
Дата: 05.03.24 15:10
Оценка: +2
Здравствуйте, K13, Вы писали:

K13>код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb


Немного оффтопа: операторы преобразования лучше объявить как explicit. Неявные преобразования — невероятно подлая штука.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Не могу понять прикола
От: rg45 СССР  
Дата: 05.03.24 17:18
Оценка: 30 (2)
Здравствуйте, K13, Вы писали:

K13>код: https://coliru.stacked-crooked.com/a/053394d0fc0b2cdb

K13>каким-то образом при наличии НЕшаблонного operator|() для конкретного enum
K13>он перестает его видеть если в неймспейсе A добавить шаблонный оператор|() который всегда отключен.
K13>Что-то я торможу. Не понимаю, что происходит при смене #if 1 / #if 0

Вот минимизированный пример, иллюстрирующий твою проблему:

https://coliru.stacked-crooked.com/a/4cd5281c9ed9ced9

#include <iostream>

namespace Qt {

enum E { _0 = 0, _1 = 1, _32 = 32};

} // namespace Qt

Qt::E operator | (Qt::E a, Qt::E b) { return Qt::E(int(a) | int(b)); }

namespace A {

#if 1 // если тут поставить 0 то все компилируется

//using ::operator |; // или если раскомментировать это объявление, то тоже все компилируется

auto operator | (class XXX&, class YYY&);

#endif

Qt::E foo() { return Qt::_1 | Qt::_32; } // error: invalid conversion from 'int' to 'Qt::E' [-fpermissive]

} // namespace A

int main()
{
    std::cout << "foo() = " << (int)A::foo() << std::endl;
}


Начать разбор лучше с конца:


Возможные способы решения:
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Не могу понять прикола
От: K13 http://akvis.com
Дата: 06.03.24 07:56
Оценка:
Здравствуйте, rg45, Вы писали:

R>Немного оффтопа: операторы преобразования лучше объявить как explicit. Неявные преобразования — невероятно подлая штука.


Q* -- это копипаст из Qt, которую мы используем.
Не думаю, что кто-то стал бы смотреть код который без Qt не компилируется.
Re[2]: Не могу понять прикола
От: K13 http://akvis.com
Дата: 06.03.24 07:58
Оценка:
Здравствуйте, rg45, Вы писали:

R>P.S. Так устроен поиск имен — компилер находит в namespace A operator | и на этом путешествие по пространствам имен прекращается.

Вот этого я не знал/забыл. Что поиск кандидатов на перегрузку прекращается.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.