Is it currently possible to constrain a class template that rejects type argument which is the specialization of the class template itself without using static_assert?
Since I cannot use requires expression to check if it is a valid typename, I have to create a class template instantiation validator that checks whether the class template passed is valid with template arguments:
template <template <typename...> typename Temp, typename... Ts>
requires requires { typename Temp<Ts...>; }
constexpr bool is_valid() { return true; }
template <template <typename...> typename, typename...>
constexpr bool is_valid() { return false; }
template <template <typename...> typename Temp, typename... Ts>
concept valid_instantiation = is_valid<Temp, Ts...>();
Since failed static_assert emits a hard error, just like this one:
template <typename>
class Hello;
template <typename>
inline constexpr bool is_hello_v = false;
template <typename T>
inline constexpr bool is_hello_v<Hello<T>> = true;
template <typename T>
class Hello {
static_assert(!is_hello_v<T>);
};
static_assert(valid_instantiation<Hello, int>);
static_assert(!valid_instantiation<Hello, Hello<int>>);
The second static assertion sure didn't compile unless I remove that ! that returns true which is not what I expected.
What I want to have is to silent the error and replace the static_assert, so that:
static_assert(valid_instantiation<Hello, int>);
static_assert(!valid_instantiation<Hello, Hello<int>>);
can be valid.
For the first static assertion, the Hello<int> instantiation is accepted just fine, while the second static assertion, Hello<Hello<int>> instantiation should be rejected because the template argument passed is the instantiation of the class template itself but I have no knowledge what constraints I'll be using to achieve these.
It's ok if it is impossible to do so, or otherwise.
Not sure it is what you want, but
template <typename T> struct is_Hello;
template <typename T> requires (!is_Hello<T>::value) class Hello;
template <typename T> struct is_Hello : std::false_type{};
template <typename T> struct is_Hello<Hello<T>> : std::true_type{};
template <typename T>
requires (!is_Hello<T>::value) // So Hello<Hello<T>> is not possible
class Hello
{
// ...
};
Not sure how you want to SFINAE or test it (the trait seems equivalent), as Hello<Hello<T>> cannot exist.
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With