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

时间:2019-04-22 18:45:32

标签: c++ class templates c++17 static-assert

说我有一个模板类,可以制作多个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>...
}

现在说我有更多的模板类需要做出相同的断言。

是否有一种方法可以使static_assert块可重用?如果愿意,可以使用“ static_assert函数”。

4 个答案:

答案 0 :(得分:3)

您可以将所需特征与描述性名称组合在一起:

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

答案 1 :(得分:3)

您可以做的一件事就是建立一个新特征,该特征是要检查的特征的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是/很痛苦的。尽管可以使用std::disjunction来获得所有特征的“或”,然后像您所做的那样对静态断言中的值求反,即可摆脱这种情况

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

答案 2 :(得分:3)

您可以定义一个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. 直接使用{strong> static_assert<> ,就像您在示例中所做的那样:

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

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

答案 3 :(得分:1)

使用结合词,我已经看到了一些很好的答案。 不幸的是,这些真的很难调试。我曾经不得不在课堂上调试一个问题,说明:满足要求。这个列表太长了,难以理解。我终于一一复制了所有基础支票。

如果可能的话,我想让它们分开:

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

在您的课堂上,您只需实例化它即可获得检查和详细的错误:

 constexpr static CustomCheck<T> check{};