如何使 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;
然后:
直接使用它static_assert<>
,就像您在示例中所做的那样:
template<typename T> class MyClass
{
static_assert(is_okay_type<T>, "message");
public:
//...code...
};
或者你可以模板的条件实例化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{};
假设我有一个模板 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;
然后:
直接使用它
static_assert<>
,就像您在示例中所做的那样:template<typename T> class MyClass { static_assert(is_okay_type<T>, "message"); public: //...code... };
或者你可以模板的条件实例化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{};