c – 在元编程中强制执行不变量
发布时间:2020-12-16 07:13:02 所属栏目:百科 来源:网络整理
导读:我希望能够检查元程序中使用的类的不变量.我的第一个天真的方法是 template int Nstruct digit{ static_assert((N = 0) (N 10),"bad invariant");};using boom = digit99; 然而,这编译没有任何问题.只有在构造非法类时才会触发静态断言. 添加其他模板参数时
我希望能够检查元程序中使用的类的不变量.我的第一个天真的方法是
template <int N> struct digit { static_assert((N >= 0) && (N < 10),"bad invariant"); }; using boom = digit<99>; 然而,这编译没有任何问题.只有在构造非法类时才会触发静态断言. 添加其他模板参数时可以: #include <type_traits> template <int N,typename = typename std::enable_if<(N >= 0) && (N < 10)>::type> struct digit; using crash = digit<-7>; 当我想将此技术应用于用作类型列表的类时: #include <type_traits> template <typename ...> struct are_integral; template <typename T,typename ...Ts> struct are_integral<T,Ts...> { static const bool value = std::is_integral<T>::value && are_integral<Ts...>::value; }; template <> struct are_integral<> : std::true_type { }; template <typename ...Ts,typename = typename std::enable_if<are_integral<Ts...>::value>::type> struct list; using ok = list<int,long,char>; using bad = list<double>; 由于gcc抱怨,它根本不起作用
即使它可以工作,该类也没用,因为模板参数包不反映类型列表. 所以我试图使用“非法”基类: template <typename> struct check; template <typename ...Ts> struct list : check<typename std::enable_if<are_integral<Ts...>::value>::type> { }; using ok = list<int,char>; using bad = list<double>; 这编译没有问题. 有没有办法在c 11中完成类似的事情,还是我必须等待概念? 解决方法
您的问题出现是因为模板在别名时未实例化,因此static_assert不会触发.
如果这是可接受的,您可以添加一些间接并使用构建器元函数来创建编译时列表.该元函数将执行检查. template <typename ...Ts> struct make_list { static_assert(are_integral<Ts...>::value,"all types must be integral"); typedef list<Ts...> type; }; using ok = make_list<int,char>::type; using bad = make_list<double>::type; 另一种解决方案是使用虚拟类型将参数包包装成第一类类型. // dummy wrapper template <typename ...> struct pack; template <typename ...> struct are_integral; // specialization for wrapped packs template <typename ...Ts> struct are_integral<pack<Ts...>> : are_integral<Ts...> { }; template <typename T,Ts...> { static const bool value = std::is_integral<T>::value && are_integral<Ts...>::value; }; template <> struct are_integral<> : std::true_type { }; // helper type which performs the check template <typename Pack,typename = typename std::enable_if<are_integral<Pack>::value>::type> struct list_helper; // actual type (alias) you will expose template <typename ...Ts> using list = list_helper<pack<Ts...>>; using ok = list<int,char>; using bad = list<double>; // compiler error 在处理参数包时,使用包装器通常会派上用场,因为它使得它们更易于操作:包装器类似于任何其他类型,其中can be stored出现在参数列表中的任何位置,传递给一元元函数等. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |