Constexpr значение как non-type template parameter

87
19 мая 2021, 21:50

Я пробовал сделать static_assert для одного конструктора сразу в std::enable_if, используя msvc.

#include <type_traits>
template <typename ... Ts>
struct typelist {};
struct nothing {};
template<bool Boolean>
constexpr bool throw_assert() {
    static_assert(Boolean);
    return Boolean;
}
template <typename T, typename ... Ts>
constexpr bool contains(typelist<Ts...> = {}) {
    return (... || std::is_same_v<T, Ts>);
}
template <typename ... Ts>
struct SomeClass {
    using type_list = typelist<Ts...>;
    constexpr SomeClass(std::enable_if_t < throw_assert < contains<nothing>(type_list{}) > () > * = 0) noexcept {}
};
int main() {
    SomeClass<int, nothing>* someClass = new SomeClass<int,nothing>();
    delete someClass;
    return 0;
}

Но компилятор ругается, что в throw_assert подается не compile-time константа. (Если оставить только contains, то все нормально). Неужели такой трюк не будет проходить?

PS: Пока писал вопрос. Оказывается такое не проходит и на clang тоже, но gcc нормально съедает. Где правильно поведение?

Answer 1

Кому интересен обход для MSVC (Работает только на 1916 и выше), на godbolt 1914 не хочет собираться):

#include <type_traits>
template <typename ... Ts>
struct typelist {};
struct nothing {};
template <typename Intergral>
inline constexpr bool throw_assert(Intergral = {}) {
    static_assert(Intergral::value);
    return Intergral::value;
}
template <typename T, typename ... Ts>
constexpr bool contains(typelist<Ts...> = {}) {
    return (... || std::is_same_v<T, Ts>);
}
template <typename T, typename ... Ts>
inline constexpr decltype(auto) contains_integral(typelist<Ts...> = {}) {
    return ::std::bool_constant<(... || ::std::is_same_v<T, Ts>)>{};
}
template <typename ... Ts>
struct SomeClass {
    using type_list = typelist<Ts...>;
    constexpr SomeClass(std::enable_if_t < throw_assert(contains_integral<nothing>(type_list{})) > * = 0) noexcept {}
};
int main() {
    SomeClass<int, nothing>* someClass = new SomeClass<int,nothing>();
    return 0;
}

PS: Правка для 1914:

...
template <typename = std::enable_if_t < throw_assert(contains_integral<nothing>(type_list{})) >>
constexpr SomeClass() noexcept {}
READ ALSO
Ищу информацию по архитектуре игр серии Worms

Ищу информацию по архитектуре игр серии Worms

Меня интересует, как внутри организованы игры серии Worms

82
Подмена маски номера телефона в зависимости от вводимой цифры

Подмена маски номера телефона в зависимости от вводимой цифры

Всем приветВообщем задачка нужно сделать маску как на https://www

114
overflow: hidden !important

overflow: hidden !important

На дисплеях с большим расширением я скрываю скролл по горизонтали

132