如何使 static_assert 块可在模板 类 中重复使用?

How to make static_assert block re-usable in template classes?

假设我有一个模板 class 可以生成多个 static_asserts:

template <class T>
class Foo
{
    static_assert(!std::is_const<T>::value,"");
    static_assert(!std::is_reference<T>::value,"");
    static_assert(!std::is_pointer<T>::value,"");

    //...<snip>...
}

现在假设我有更多模板 classes 需要做出相同的断言。

有没有办法使 static_assert 块可重用? "static_assert function" 如果你愿意的话。

您可以将所需的特征组合成一个具有描述性名称的特征:

template<typename T> using
is_fancy = ::std::integral_constant
<
    bool
,   (not std::is_const<T>::value)
    and
    (not std::is_reference<T>::value)
    and
    (not std::is_pointer<T>::value)
>;

稍后使用:

static_assert(std::is_fancy<T>::value,"");

您可以做的一件事是构建一个新特征,它是您要检查的特征的 conjunction。因为你想要否定所有那些字面上会转化为

的特征
template<typename T>
using my_trait = std::conjunction<std::negation<std::is_const<T>>,
                                  std::negation<std::is_reference<T>>,
                                  std::negation<std::is_pointer<T>>>;

static_assert(my_trait<int>::value, "");

但必须为每个特征使用 std::negation is/can 是一种痛苦。你可以通过使用 std::disjunction 来获得所有特征的 "or" 来摆脱它,然后像你一样否定静态断言中的值,这会给你

template<typename T>
using my_trait = std::disjunction<std::is_const<T>,
                                  std::is_reference<T>,
                                  std::is_pointer<T>>;

static_assert(!my_trait<int>::value, "");

您可以定义一个 constexpr bool 在编译时进行计算:

template<typename T>
inline constexpr bool is_okay_type = !std::is_const<T>::value &&
                                     !std::is_reference<T>::value &&
                                     !std::is_pointer<T>::value;

然后:

  1. 直接使用它static_assert<>,就像您在示例中所做的那样:

    template<typename T> class MyClass
    {
        static_assert(is_okay_type<T>, "message");
    public:
        //...code...
    };
    
  2. 或者你可以模板的条件实例化class, 取决于模板参数。

    template<typename Type, typename Enable = void> class Class1;
    
    template<typename Type>
    class Class1<Type, std::enable_if_t<is_okay_type<Type>> >
    {
        //...code...
    };
    

我看到了一些很好的答案,使用连词。 不幸的是,这些真的很难调试。我曾经不得不调试我的 class 声明的问题:满足要求。这是一份太长的清单,难以理解。我终于把所有的底层支票都一张一张地抄了下来

如果可能,我喜欢将它们分开:

template<typename T>
struct CustomCheck {
     static_assert(check<T>);
      // ...
 };

在您的 class 中,您只需将其实例化即可获得检查和详细错误:

 constexpr static CustomCheck<T> check{};