【问题标题】:Boost MPL Sorting Template Parameter PackBoost MPL 排序模板参数包
【发布时间】:2018-04-22 13:42:35
【问题描述】:

我要解决的问题是根据我要排序的每种类型专用的 constexpr 模板函数的返回值对模板参数包进行排序。

我有一个大约 100 个 BOOST_STRONG_TYPEDEFs 的列表,它们创建了 TYPE_1, TYPE_2, ..., TYPE_N 类型。

BOOST_STRONG_TYPEDEF(TYPE_1, int)
BOOST_STRONG_TYPEDEF(TYPE_2, double)
// et cetera
BOOST_STRONG_TYPEDEF(TYPE_N, uint8_t)

然后我声明一个通用模板constexpr size_t value_of(),我专门针对我的每一种类型:

template<> constexpr size_t value_of<TYPE_1>() { return 1; }
template<> constexpr size_t value_of<TYPE_2>() { return 2; }
// et cetera
template<> constexpr size_t value_of<TYPE_N>() { return n; }

然后我有一个声明如下的类。我需要根据value_of的结果对UnsortedTypes参数包中的每个类型进行排序。

template<typename ...UnsortedTypes>
class MyClass {
  typedef boost::mpl::vector<UnsortedTypes...> UnsortedTypeVector;
  typedef typename boost::mpl::sort<
    UnsortedTypeVector,
    boost::mpl::less<
      boost::mpl::size_t<value_of<boost::mpl::placeholders::_1>()>,
      boost::mpl::size_t<value_of<boost::mpl::placeholders::_2>()>
    >
  >::type SortedTypes;

  // Utility
  void print_types() {
    __print_types<SortedTypes>();
  }

  template<typename Type, typename ...Types>
  void __print_types() {
    std::cout << typeid(Type).name() << "\n";
    if constexpr (sizeof...(Types) > 0) __print_types<Types...>();
  }
};

当我如下测试时:

int main(int, char *[]) {
  MyClass<TYPE_5, TYPE_3, TYPE_4, TYPE_2, TYPE_1> myclass;
  myclass.print_types();
}

我收到了这个huge, pretty much unintelligible error message,它似乎包含 mpl 库中的错误。

直觉上,我怀疑这是由于我的排序谓词定义不正确造成的。但是,我不确定如何解决它!

(这是我第一次使用Boost.MPL,网上的例子不多,所以请温柔!)

【问题讨论】:

    标签: c++ boost c++17 variadic-functions boost-mpl


    【解决方案1】:

    这是一个简化的示例,可能会使正在发生的事情更加明显:

    namespace mpl = boost::mpl;
    
    template <typename T> constexpr size_t value_of() { return sizeof(T); }
    
    template <typename... Ts>
    struct X {
        using V = mpl::vector<Ts...>;
        using sorted = typename mpl::sort<
            V,
            mpl::less<
                mpl::size_t<value_of<mpl::_1>()>,
            //              ~~~~~~~~~~~~~~~~~~~
                mpl::size_t<value_of<mpl::_2>()>
                >
            >::type;
    };
    

    现在,您打算延迟 value_of() 的调用,直到 _1 被替换。但实际上发生的是它会立即被调用——因为这就是你所要求的。就我而言,这就是sizeof(_1) 的最终结果。因此,由于这些都是常量,完整的 mpl::less&lt;...&gt; 只是一些完整的常量表达式 - 而不是像您希望的那样是 lambda 表达式。

    您需要做的是通过将谓词转换为元函数来确保调用被延迟:

    template <typename T>
    struct value_of_ : mpl::size_t<sizeof(T)> { };
    

    然后你可以使用:

    template <typename... Ts>
    struct X {
        using V = mpl::vector<Ts...>;
        using sorted = typename mpl::sort<
            V,
            mpl::less<value_of_<mpl::_1>, value_of_<mpl::_2>>
            >::type;
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-30
      相关资源
      最近更新 更多