eth*_*ice 7 c++ boost boost-mpl template-meta-programming c++11
在以下代码中(为演示而简化):
namespace mpl = boost::mpl;
using if1 = mpl::if_<std::is_same<double, mpl::_1>, double, void>;
//using if2 = mpl::if_<std::is_same<double, mpl::_1>, typename std::common_type<double, mpl::_1>::type, void>;
using apply1 = boost::mpl::apply<if1, double>::type;
//using apply2 = boost::mpl::apply<if2, double>::type;
Run Code Online (Sandbox Code Playgroud)
在std::is_same<double, mpl::_1>,占位符被正确替换double,就好像实例化明确std::is_same<double, double>导致正确/预期的行为.
但是,在std::common_type<double, mpl::_1>占位符中没有替换占位符,就好像实例化是明确的std::common_type<double, mpl_::arg<1>>,这会导致以下错误,因为显然没有"常见"类型:
error: incompatible operand types ('double' and 'mpl_::arg<1>')
Run Code Online (Sandbox Code Playgroud)
问题:为什么mpl::_1占位符正确转换/置换double的std::is_same,而不是在std::common_type?有解决方法吗?
你通过访问嵌套迫使急于实例::type的std::common_type应用拉姆达之前.替换typename std::common_type<double, mpl::_1>::type为std::common_type<double, mpl::_1>,你应该都很好.
编辑:抱歉不好的建议.我没看到你在做什么.麻烦的是,mpl::apply首先运行它会将占位符表达式转换为lambda表达式mpl::lambda.这将导致std::common_type<double, mpl::_1>包装在一个mpl::protect,它将阻止它在第一次传递中被评估,并且mpl::if_不会在第二次传递中评估它,因为它将其第二个和第三个参数视为普通类型,而不是占位符表达式.您可以使用mpl::bind强制std::common_type进行评估之前 mpl::if_.那样,mpl::if_看到了if_<some-condition, double, void>,一切都是对的.
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/quote.hpp>
namespace mpl = boost::mpl;
template<typename T, typename U> using common_type2 = std::common_type<T,U>;
using if2 = mpl::if_<
std::is_same<double, mpl::_1>,
mpl::bind<mpl::quote2<common_type2>, double, mpl::_1>,
void>;
using apply2 = boost::mpl::apply<if2, double>::type;
static_assert(std::is_same<apply2, double>::value, "works");
Run Code Online (Sandbox Code Playgroud)
HTH!