170 похожих чатов

Template <typename U, bool T = true> class C{ public: template<typename = std::enable_if_t<!T>> explicit

C(int x, int y){}
template<typename = std::enable_if_t<T>>
explicit C(int x) {}
};

int main(){

C<int> a(2);

return 0;
}

почему такое компилится msvc и не компилится gcc и клангом. Где баг где фича?

10 ответов

29 просмотров
Pepe 🐸- Автор вопроса

По идее не должно компилиться, потому что substitution тут нет, но msvc компилит

Упрощу пример, убрав всё лишнее: template <bool T> class C { public: template<typename = std::enable_if_t<!T>> void foo(){} }; // ... C<true> a{}; По сути, когда мы инстанцируем C, мы получаем эквивалент следующего псевдокода: template <> class C<true> { public: template<typename = std::enable_if_t<!true>> void foo(){} }; Так что да, enable_if_t всегда содержит ложное условие для текущей специализации C, что равнозначно написанию std::enable_if_t<false> в любом нешаблонном контексте — это всегда ошибка компиляции и SFINAE не спасает потому что тут нет SFINAE-контекста. GCC и Clang, кажется правы Могу лишь предположить, что MSVC откладывает момент инстанцирования дефолтного параметра функции до инстанцирования самого шаблона функции

Ofee Oficsu
Упрощу пример, убрав всё лишнее: template <bool T...

Интересно, что констрейнты справляются: template <bool B> struct C { void foo() requires (!B) {} }; int main() { C<true> a; } При этом вызов a.foo() будет ошибкой. Я попытался придумать как воспроизвести исключение метода из класса без requires и такое чувство, что никак. Приходят в голову методы-уродцы исключить через CRTP (наследуясь от базового класса в котором есть или нет и т.п.), но если поставить условие обойтись без наследования, то интересно есть ли метод воспроизвести шаблонной магией то, что легко делают констрейнты?

Konstantin Vladimirov
Интересно, что констрейнты справляются: template ...

template <bool B> struct X { template <bool B_ = B, [sfinae on B_]> void foo(); }; Должно решить проблему

Konstantin Vladimirov
Интересно, что констрейнты справляются: template ...

>> Интересно, что констрейнты справляются Да, если не ошибаюсь, это намеренно заложенное в них поведение, чтобы упростить включение/выключение функций в зависимости от параметров класса (в том числе деструктора)

Alexander Karaev
template <bool B> struct X { template <bool B_ =...

Да, логично, спасибо. Я чего-то не подумал. Просто распространяем SFINAE вниз. И так же чинится оригинальный кейс от @scaredpepe https://godbolt.org/z/3Yro8GnYd

Ofee Oficsu
>> Интересно, что констрейнты справляются Да, есл...

без этого зачем вообще они нужны были бы?)

Kelbon
без этого зачем вообще они нужны были бы?)

Довольно странное заявление при том, что они: 1) значительно упрощают код; 2) зависимы между собой и позволяют "перегрузки"; 3) лучше понятны компилятору, что потенциально упрощает и ускоряет диагностику ошибок компилятором

Konstantin Vladimirov
Да, логично, спасибо. Я чего-то не подумал. Просто...

Я бы добавил ещё один интересный хак: template <bool B> struct X { template <typename..., bool B_ = B, [sfinae on B_]> void foo(); }; Это не позволит случайно переопределить дефолтный параметр извне. По желанию добавить ограничение ещё и на то, чтобы пак был пуст

Pepe 🐸- Автор вопроса
Ofee Oficsu
Упрощу пример, убрав всё лишнее: template <bool T...

Да, только получается MSVC вообще не инстанцирует его

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

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Ребят в СИ можно реализовать ООП?
Николай
33
у вас два процесса. один посылает другому сигнал. у вас есть код обоих процессов? если всё не так - расскажите как оно на самом деле. а именно кто кому чего, есть-ли консоли,...
Karagy
6
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Карта сайта