Boost MPL排序模板参数包
Boost MPL Sorting Template Parameter Pack
我要解决的问题是根据专用于我正在排序的每种类型的 constexpr 模板函数的 return 值对模板参数包进行排序。
我有一个大约 100 BOOST_STRONG_TYPEDEF
的列表,它创建类型 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; }
然后我有一个class声明如下。我需要根据 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,网上例子不多,大家多多包涵!)
这是一个简化的示例,可能会使发生的事情更加明显:
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<...>
只是一些整数常量表达式 - 而不是像您希望的那样是 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;
};
我要解决的问题是根据专用于我正在排序的每种类型的 constexpr 模板函数的 return 值对模板参数包进行排序。
我有一个大约 100 BOOST_STRONG_TYPEDEF
的列表,它创建类型 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; }
然后我有一个class声明如下。我需要根据 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,网上例子不多,大家多多包涵!)
这是一个简化的示例,可能会使发生的事情更加明显:
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<...>
只是一些整数常量表达式 - 而不是像您希望的那样是 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;
};