我如何static_assert
喜欢这个?如果没有C ++或C ++ 11中的新功能,Boost可能会支持它吗?
template<T>
struct foo {};
template<FooType>
struct bar {
static_assert(FooType is indeed foo<T> for some T,"failure"); //how?
};
答案 0 :(得分:26)
你可以沿着这些方向做点什么。给定一个特性可以验证类是否是类模板的实例化:
#include <type_traits>
template<typename T, template<typename> class TT>
struct is_instantiation_of : std::false_type { };
template<typename T, template<typename> class TT>
struct is_instantiation_of<TT<T>, TT> : std::true_type { };
在程序中使用如下:
template<typename T>
struct foo {};
template<typename FooType>
struct bar {
static_assert(is_instantiation_of<FooType, foo>::value, "failure");
};
int main()
{
bar<int> b; // ERROR!
bar<foo<int>> b; // OK!
}
如果需要,可以将其概括为检测类是否是具有任意数量(类型)参数的模板的实例,如下所示:
#include <type_traits>
template<template<typename...> class TT, typename T>
struct is_instantiation_of : std::false_type { };
template<template<typename...> class TT, typename... Ts>
struct is_instantiation_of<TT, TT<Ts...>> : std::true_type { };
template<typename FooType>
struct bar {
static_assert(is_instantiation_of<foo, FooType>::value, "failure");
};
然后您将在程序中以这种方式使用它:
template<typename FooType>
struct bar {
static_assert(is_instantiation_of<foo, FooType>::value, "failure");
};
int main()
{
bar<int> b; // ERROR!
bar<foo<int>> b; // OK!
}
这是live example。
答案 1 :(得分:2)
正如别人写的那样,
template<typename T, template<typename...> class TT>
struct is_specialization_of : std::false_type { };
template<template<typename...> class TT, typename... Ts>
struct is_specialization_of<TT<Ts...>, TT> : std::true_type { };
但是,请注意,这仅适用于模板类,其模板参数都是类型名称!提供
typedef std::array<int, 42> MyArray;
static_assert(is_specialization_of<MyArray, std::array>::value, "");
根本无法编译。
我相信C ++ 11 / C ++ 14 / C ++ 17目前无法解决这个限制。
答案 2 :(得分:0)
与其他答案相比有一些小改进:
const
,volatile
和引用类型constexpr
变量我故意不将std :: decay_t放在is_template_for_v上,因为类型特征应该以相同的方式工作,无论是否使用_v后缀调用它。
这需要std::conjunction
的C ++ 17,但您可以使用c ++ 11/14删除可变参数功能或实现自己的conjunction
。
template<template<class...> class tmpl, typename T>
struct _is_template_for : public std::false_type {};
template<template<class...> class tmpl, class... Args>
struct _is_template_for<tmpl, tmpl<Args...>> : public std::true_type {};
template<template<class...> class tmpl, typename... Ts>
using is_template_for = std::conjunction<_is_template_for<tmpl, std::decay_t<Ts>>...>;
template<template<class...> class tmpl, typename... Ts>
constexpr bool is_template_for_v = is_template_for<tmpl, Ts...>::value;
用法:
static_assert(is_template_for_v<std::vector, std::vector<int>>); // doesn't fire