如何在MSVC中正确使用BOOST_HOF_LIFT与BOOST_HOF_LIFT_CLASS宏
你遇到的两个错误分别来自MSVC的编译器缺陷,和对BOOST_HOF_LIFT_CLASS宏的用法错误,对应的解决方案如下:
1. 替换模板变量为模板函数绕开MSVC缺陷
BOOST_HOF_LIFT本质是返回一个函数对象的宏,你之前用模板变量存储返回值的写法触发了MSVC对模板变量内lambda表达式的实例化bug,改为用模板函数返回BOOST_HOF_LIFT的结果即可兼容MSVC:
#include <boost/hof.hpp> #include <tuple> #include <cassert> template<int N> constexpr auto getNth_a() { return BOOST_HOF_LIFT(std::get<N>); } int main() { std::tuple<int,int> t{1,2}; // 调用时多写一对括号即可 assert(getNth_a<0>()(t) == 1); }
这个写法在GCC、Clang、MSVC下都可以正常编译运行。
2. 修正BOOST_HOF_LIFT_CLASS的用法
BOOST_HOF_LIFT_CLASS的作用是直接生成一个非模板类,不能直接在模板作用域内用它生成依赖模板参数的类型,必须把它嵌套到模板结构体内部使用:
#include <boost/hof.hpp> #include <tuple> #include <cassert> template<int N> struct getNth_b { // 把LIFT_CLASS生成的类放到模板结构体内部,作为依赖类型 BOOST_HOF_LIFT_CLASS(type, std::get<N>); }; // 可选:搭配别名模板简化调用,避免每次写typename template<int N> using getNth_b_t = typename getNth_b<N>::type; int main() { std::tuple<int,int> t{1,2}; // 基础用法 assert(typename getNth_b<0>::type()(t) == 1); // 用别名模板的简化用法 assert(getNth_b_t<0>()(t) == 1); }
替代方案(C++20及以上)
如果你的项目可以使用C++20,完全可以不用Boost.HOF的宏,直接用模板lambda实现同样的功能,兼容性更好:
#include <tuple> #include <cassert> template<int N> constexpr auto getNth = []<typename T>(T&& tuple) noexcept(noexcept(std::get<N>(std::forward<T>(tuple)))) -> decltype(auto) { return std::get<N>(std::forward<T>(tuple)); }; int main() { std::tuple<int,int> t{1,2}; assert(getNth<0>(t) == 1); }
这个写法在MSVC、GCC、Clang下都可以直接用getNth<0>(t)的方式调用,没有兼容性问题。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

