7

在以下代码中(为演示而简化):

  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;

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>')


问题:为什么mpl::_1占位符被正确转换/替换为doublein std::is_same而不是in std::common_type?有没有解决方法?


4

1 回答 1

6

通过在应用 lambda 之前访问嵌套::type的 of来强制实例化过于急切。std::common_type替换typename std::common_type<double, mpl::_1>::typestd::common_type<double, mpl::_1>,你应该一切都好。

编辑:为不好的建议道歉。我没看清楚你在做什么。麻烦的是,这mpl::apply会将您的占位符表达式转换为 lambda 表达式,方法是首先通过mpl::lambda. 这将导致std::common_type<double, mpl::_1>被包裹在一个 中mpl::protect,这将阻止它在第一遍中被评估,并且mpl::if_不会在第二遍中评估它,因为它将其第二个和第三个参数视为普通类型,而不是占位符表达式。您可以使用mpl::bindto 强制之前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");

于 2013-11-05T22:09:59.003 回答