假设我有一个模板类,它产生多个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函数”。
你可以做的一件事是建立一个新的特征,这是你要检查的特征的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, "");
您可以将所需特征组合成具有描述性名称的特征:
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,"");
您可以定义一个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...
};
template<typename Type, typename Enable = void> class Class1;
template<typename Type>
class Class1<Type, std::enable_if_t<is_okay_type<Type>> >
{
//...code...
};
我已经看到了几个很好的答案,使用了连接。不幸的是,这些都很难调试。我曾经不得不调试我班上的一个问题:满足要求。这是一个太长的清单无法理解。我终于一个一个地复制了所有基础检查。
如果可能的话,我喜欢让他们分开:
template<typename T>
struct CustomCheck {
static_assert(check<T>);
// ...
};
在您的类中,您只需要实例化它以获取检查和详细错误:
constexpr static CustomCheck<T> check{};