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

问题描述 投票:3回答:4

假设我有一个模板类,它产生多个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函数”。

c++ class templates c++17 static-assert
4个回答
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, "");

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

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. 直接使用它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... };

1
投票

我已经看到了几个很好的答案,使用了连接。不幸的是,这些都很难调试。我曾经不得不调试我班上的一个问题:满足要求。这是一个太长的清单无法理解。我终于一个一个地复制了所有基础检查。

如果可能的话,我喜欢让他们分开:

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

在您的类中,您只需要实例化它以获取检查和详细错误:

 constexpr static CustomCheck<T> check{};
© www.soinside.com 2019 - 2024. All rights reserved.