c – 将数字隐式转换为整数const
假设我有这个功能:
template<size_t N> void foo(std::integral_constant<size_t,N>); 现在使用它我这样做: constexpr size_t myNum = 12; foo(std::integral_constant<size_t,myNum>()); 但是我希望有一种方法可以像这样使用它: constexpr size_t myNum = 12; foo(myNum); 有没有办法将数字隐式转换为相应的std :: integral_constant? 解决方法
我担心真正的隐式转换是不可能的.但是,您可以使用宏和编译时常量检测(请参阅
https://stackoverflow.com/a/13305072/6846474)来模拟所需的语法以及“
constexpr overloading”.
这是我的C 14实现的诀窍: #include <iostream> // Compile-time constant detection for C++11 and newer template <typename T> constexpr typename std::remove_reference<T>::type makeprval(T && t) { return t; } #define is_const(X) noexcept(makeprval(X)) // broken in Clang //#define is_const(X) __builtin_constant_p(X) // non-standard but works in GCC and Clang template <bool c> struct const_var_impl { template <typename CFn,typename VFn> static inline auto resolve_branch(CFn cf,VFn vf) {} }; template <> struct const_var_impl<true> { template <typename CFn,VFn vf) { return cf(); } }; template <> struct const_var_impl<false> { template <typename CFn,VFn vf) { return vf(); } }; #define const_var_branch(X,F) const_var_impl<is_const(X)>::resolve_branch( [&]() { constexpr auto _x_val = is_const(X) ? X : 0; return F(std::integral_constant<decltype(X),_x_val>{}); }, [&]() { return F(X); } ) template <typename T,T c> void fn_impl(std::integral_constant<T,c> c_arg) { std::cout << "Constant " << c_arg << std::endl; } template <typename T> void fn_impl(T v_arg) { std::cout << "Variable " << v_arg << std::endl; } #define fn(X) const_var_branch(X,fn_impl) int main(void) { int n = 2; fn(1); // Prints "Constant 1" fn(n); // Prints "Variable 2" return 0; } 您必须使用宏,因为只有常量文字或constexpr表达式被视为编译时常量.据我所知,无法检测到恒定传播. 所以,我们有两个fn_impl重载.编译时和运行时实现. 主要思想是使用两个lambda函数,其中一个将根据is_const(X)的值调用.在将常量/变量X显式转换为正确类型后,每个lambda都会调用两个重载之一.正确的lambda将通过const_var_impl的模板特化来调用. 棘手的部分是使这项工作没有编译器错误.你不得不从const_var_branch宏中取出X并尝试从中创建integral_constant,如果X是非常量的话,这是不可能的. 幸运的是,我们可以这样做: constexpr auto _x_val = is_const(X) ? X : 0; 现在代码始终有效.如果X是常量,我们得到它的值并用它实例化integral_constant.否则我们最终会得到零,这很好,因为无论如何都不会调用具有编译时实现的lambda. 这种方法的明显局限性在于,对于我们想要重载的每个函数,我们必须创建一个宏并将其用于调用.如果我们想在命名空间内调用方法或函数,这当然不实用. 要解决这个问题,我们可以创建一个仅包装函数参数的类似宏: #define var_or_const(X) const_var_branch(X,[](auto && x) {return x;}) 该宏返回某个整数类型T的X或std :: integral_constant< T,X>的实例. 然后我们将直接在fn_impl上使用它: fn_impl(var_or_const(n)); 然而,这仍然不是隐含的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ruby-on-rails – Rails 3到4迁移唯一性验证问题
- c# – 如何获取基类的泛型参数?
- cocos2dx 3.2 ScrollView 2个bug(滚动方向相反和jump函数不
- ruby-on-rails – ActiveRecord,不包括记录!=?
- rapidxml vtd-xml性能对比,备忘
- ruby – eval和binding:它们有用吗?
- adt 开发环境下直接查询sqlite数据库工具
- 聚合类
- c# – 在Visual Studio Windows Azure模拟器下运行ASP.NET
- c# – VirtualizingStackPanel和TextWrapping错误? Window