Из-за чего requires!std::is_void_v работает только для шаблона?
Ссылка скопирована
T& GetValue() const requires !std::is_void_v<T> //C7683 { return *_value; } template<typename TValue = T> requires !std::is_void_v<TValue> TValue& GetValueAs() const { return static_cast<TValue&>(*_value); }
Нужно решить такую задачу?
Заказать помощь
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Лучший ответ
1
Другие ответы (0)
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопроскомментарий
Вам также может быть интересно
VPN
Как правильно настроить vless для Android TV?
1 ответ
Pyrogram
Как правильно зарегистрировать юзер бота в Telegram?
1 ответ
печатные-платы
Как заставить запускаться программу M3.exe от компании Hanxing AOI в инспекционной машине на Windows 7 Pro?
1 ответ
code-review
Нужен ли код-ревью React/TypeScript проекта?
1 ответ

Проблема в том, что requires у обычного метода класса зависит от параметров шаблона класса, а не от параметров самого метода. Если T - параметр шаблона класса, то выражение requires !std::is_void_v<T> должно быть корректно в контексте инстанцирования класса. В некоторых компиляторах/режимах Visual C++ можно получить C7683, если constrained non-template member пытается использовать условие так, как будто оно SFINAE-отключает метод.
Шаблонный метод GetValueAs работает, потому что TValue - параметр шаблона самого метода. Constraint применяется к конкретной подстановке метода, и компилятору проще исключить его из overload set.
Один из рабочих вариантов - сделать GetValue тоже шаблонным с параметром по умолчанию:
template<typename TValue = T> TValue& GetValue() const requires (!std::is_void_v<TValue>) { return static_cast<TValue&>(*_value); }
Если возвращать нужно именно T&, можно так:
template<typename TValue = T> T& GetValue() const requires (!std::is_void_v<TValue>) { return *_value; }
Но если T может быть void, поле _value тоже должно быть устроено так, чтобы для void оно не требовало T& или разыменования. Иначе метод вы отключите, но класс все равно может быть некорректен из-за хранения void.
Еще вариант - специализировать класс для void или вынести value-хранилище в helper, который по-разному устроен для void и не-void.
Вывод: ваш второй вариант работает не случайно, а потому что constraint привязан к шаблонному параметру метода. Для максимальной совместимости с MSVC сделайте GetValue шаблонным или разделите специализации класса. Это нормальная практика для API, где T может быть void.