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 ответов

32 просмотра
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 вообще не инстанцирует его

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Гайс, вопрос для разносторонее развитых: читаю стрим с юарта, нада выделять с него фреймы с определенной структурой, если ли чо готовое, или долбаться с ринг буффером? нада у...
Vitaly
9
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
длина пакета фиксированная, или меняется?
Okhsunrog
7
Карта сайта