如何通过禁用专业化本身的类型参数来约束 class 模板,为什么(不)它起作用?

How to constrain class template by disabling type argument of specialization itself, and why does(n't) it work?

目前是否可以在不使用 static_assert 的情况下约束拒绝类型参数的 class 模板,这是 class 模板本身的特化?

因为我不能使用 requires 表达式来检查它是否是一个有效的类型名,我必须创建一个 class 模板实例化验证器来检查传递的 class 模板是否有效使用模板参数:

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...>();

因为失败 static_assert 发出一个硬错误,就像这个:

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>>);

第二个静态断言肯定没有编译,除非我删除 ! 那个 returns true 这不是我所期望的。

我想要的是消除错误并替换 static_assert,以便:

static_assert(valid_instantiation<Hello, int>);
static_assert(!valid_instantiation<Hello, Hello<int>>);

可以有效。

对于第一个静态断言,Hello<int> 实例化被接受得很好,而第二个静态断言,Hello<Hello<int>> 实例化应该被拒绝,因为传递的模板参数是 class 模板本身,但我不知道我将使用什么约束来实现这些。

做不到也没关系,否则没关系。

不确定这是否是您想要的,但是

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
{
// ...
};

不确定你想如何进行 SFINAE 或测试它(特征似乎是等同的),因为 Hello<Hello<T>> 不存在。

Demo