确定升压变体中的最大 sizeof()
Determining largest sizeof() in boost variant
鉴于:
boost::variant<T1,T2,T3,...,TN>
编译时计算如下:
max(sizeof(T1), sizeof(T2), sizeof(T3),... ,sizeof(TN))
我不知道如何处理这个问题,但 this 的回答让我明白了如何开始。使用该答案中的代码 T1
和 T2
,我可以在源文件中使用以下代码来获取较大对象的大小:
size_t largestSize = sizeof(largest<T1, T2>::type);
这正是我想要做的,但我需要 largest
模板来处理两个以上的 类 - 具体来说,它需要检查存储在boost::variant
对象。
我知道 boost::variant
有一个 types
typedef,它定义了变体中的某种类型列表。问题是,当我试图围绕实施中的所有 boost::mpl
内容进行思考时,我完全迷失了方向。我不直观地理解 boost::variant::types
是什么 ,以及我如何能够将它传递到我自己的模板中来处理它。
在我看来,这就是最终实现的样子:
typedef boost::variant<T1, T2, T3, T4> MyVariant;
size_t largestSize = sizeof(largest<MyVariant::types>::type);
不幸的是,我不知道如何着手实施这个版本的 largest
。
我不确定这是否是一种合理的方法,所以我愿意接受任何其他方法来实现这一点(也许在编译时对所有类型应用 boost::static_visitor
?)。
忽略 mpl 的东西。开始于:
template <class T> struct max_variant_sizeof;
template <class... Ts>
struct max_variant_sizeof<boost::variant<Ts...>> {
static constexpr size_t value = variadic_max(sizeof(Ts)...);
};
现在 max_variant_sizeof<MyVariant>::value
会将所有类型的所有大小转发给一个函数。您需要做的就是写 variadic_max
:
constexpr size_t variadic_max(size_t v) { return v; }
template <class... Args>
constexpr size_t variadic_max(size_t a, size_t b, Args... cs)
{
return variadic_max(std::max(a, b), cs...);
}
在 C++14 之前,std::max()
不是 constexpr
,因此可以替换为:
return variadic_max((a > b ? a : b), cs...);
值得注意的一件事:
maybe apply a boost::static_visitor
to all types at compile time?
使用 variant
的访问是一个 运行时 操作 - 您的访问者被调用时 variant
恰好持有的类型。它不会用 all 类型调用。
您还可以更改附加到 link 的代码:
template <class First, class... Args>
struct largest: largest<First, typename largest<Args...>::type> {
};
template<bool, typename T1, typename T2>
struct is_cond {
typedef T1 type;
};
template<typename T1, typename T2>
struct is_cond<false, T1, T2> {
typedef T2 type;
};
template<typename T1, typename T2>
struct largest<T1, T2> {
typedef typename is_cond< (sizeof(T1)>sizeof(T2)), T1, T2>::type type;
};
那么用法可能是这样的:
cout << sizeof(largest<int, char, double>::type) << endl;
编辑:
要使其与 boost::variant 以及任何其他模板化的可变参数一起工作 class 只需添加另一个特化:
template <template <class...> class Var, class... Args>
struct largest<Var<Args...>>: largest<Args...> { };
然后用法可能看起来像(有元组,可以成功改成boost::variant):
cout << sizeof(largest<tuple<int, char, double>>::type) << endl;
我已经使用 boost::mpl
库作为编译时代码操作的通用库。
一些头代码准备:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/type_traits/alignment_of.hpp>
// alignof_ headers
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/aux_/na_spec.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
// alignof mpl style implementation (namespace injection) the same way as the `mpl::sizeof_` did
namespace boost {
namespace mpl {
template<
typename BOOST_MPL_AUX_NA_PARAM(T)
>
struct alignof_
: mpl::size_t< boost::alignment_of<T>::value >
{
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, alignof_, (T))
};
BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, alignof_)
}
}
'
一些辅助宏:
// generates compilation error and shows real type name (and place of declaration in some cases) in an error message, useful for debugging boost::mpl recurrent types
// old C++ standard compatible
//#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
// (*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)
// can be applied in a class, but requires `decltype` support
#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
typedef decltype((*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)) _type_lookup_t
namespace utility
{
struct dummy {};
template <typename T>
struct type_lookup
{
typedef T type;
};
}
'
用法示例:
namespace mpl = bost::mpl;
typedef mpl::vector<T1, T2, T3, T4, T5> storage_types_t;
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::sizeof_<mpl::_1> >
>::type
>::type max_size_t; // type has stored max sizeof(T1, T2, T3, T4, T5)
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::alignof_<mpl::_1> >
>::type
>::type max_alignment_t; // type has stored max alignof(T1, T2, T3, T4, T5)
// testing on real values
UTILITY_TYPE_LOOKUP_BY_ERROR(max_size_t);
UTILITY_TYPE_LOOKUP_BY_ERROR(max_alignment_t);
'
Visual Studio 2015 错误输出:
error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max sizeof here**>'
error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max alignment here**>'
鉴于:
boost::variant<T1,T2,T3,...,TN>
编译时计算如下:
max(sizeof(T1), sizeof(T2), sizeof(T3),... ,sizeof(TN))
我不知道如何处理这个问题,但 this 的回答让我明白了如何开始。使用该答案中的代码 T1
和 T2
,我可以在源文件中使用以下代码来获取较大对象的大小:
size_t largestSize = sizeof(largest<T1, T2>::type);
这正是我想要做的,但我需要 largest
模板来处理两个以上的 类 - 具体来说,它需要检查存储在boost::variant
对象。
我知道 boost::variant
有一个 types
typedef,它定义了变体中的某种类型列表。问题是,当我试图围绕实施中的所有 boost::mpl
内容进行思考时,我完全迷失了方向。我不直观地理解 boost::variant::types
是什么 ,以及我如何能够将它传递到我自己的模板中来处理它。
在我看来,这就是最终实现的样子:
typedef boost::variant<T1, T2, T3, T4> MyVariant;
size_t largestSize = sizeof(largest<MyVariant::types>::type);
不幸的是,我不知道如何着手实施这个版本的 largest
。
我不确定这是否是一种合理的方法,所以我愿意接受任何其他方法来实现这一点(也许在编译时对所有类型应用 boost::static_visitor
?)。
忽略 mpl 的东西。开始于:
template <class T> struct max_variant_sizeof;
template <class... Ts>
struct max_variant_sizeof<boost::variant<Ts...>> {
static constexpr size_t value = variadic_max(sizeof(Ts)...);
};
现在 max_variant_sizeof<MyVariant>::value
会将所有类型的所有大小转发给一个函数。您需要做的就是写 variadic_max
:
constexpr size_t variadic_max(size_t v) { return v; }
template <class... Args>
constexpr size_t variadic_max(size_t a, size_t b, Args... cs)
{
return variadic_max(std::max(a, b), cs...);
}
在 C++14 之前,std::max()
不是 constexpr
,因此可以替换为:
return variadic_max((a > b ? a : b), cs...);
值得注意的一件事:
maybe apply a
boost::static_visitor
to all types at compile time?
使用 variant
的访问是一个 运行时 操作 - 您的访问者被调用时 variant
恰好持有的类型。它不会用 all 类型调用。
您还可以更改附加到 link 的代码:
template <class First, class... Args>
struct largest: largest<First, typename largest<Args...>::type> {
};
template<bool, typename T1, typename T2>
struct is_cond {
typedef T1 type;
};
template<typename T1, typename T2>
struct is_cond<false, T1, T2> {
typedef T2 type;
};
template<typename T1, typename T2>
struct largest<T1, T2> {
typedef typename is_cond< (sizeof(T1)>sizeof(T2)), T1, T2>::type type;
};
那么用法可能是这样的:
cout << sizeof(largest<int, char, double>::type) << endl;
编辑:
要使其与 boost::variant 以及任何其他模板化的可变参数一起工作 class 只需添加另一个特化:
template <template <class...> class Var, class... Args>
struct largest<Var<Args...>>: largest<Args...> { };
然后用法可能看起来像(有元组,可以成功改成boost::variant):
cout << sizeof(largest<tuple<int, char, double>>::type) << endl;
我已经使用 boost::mpl
库作为编译时代码操作的通用库。
一些头代码准备:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/type_traits/alignment_of.hpp>
// alignof_ headers
#include <boost/mpl/size_t.hpp>
#include <boost/mpl/aux_/na_spec.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
// alignof mpl style implementation (namespace injection) the same way as the `mpl::sizeof_` did
namespace boost {
namespace mpl {
template<
typename BOOST_MPL_AUX_NA_PARAM(T)
>
struct alignof_
: mpl::size_t< boost::alignment_of<T>::value >
{
BOOST_MPL_AUX_LAMBDA_SUPPORT(1, alignof_, (T))
};
BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, alignof_)
}
}
'
一些辅助宏:
// generates compilation error and shows real type name (and place of declaration in some cases) in an error message, useful for debugging boost::mpl recurrent types
// old C++ standard compatible
//#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
// (*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)
// can be applied in a class, but requires `decltype` support
#define UTILITY_TYPE_LOOKUP_BY_ERROR(type_name) \
typedef decltype((*(::utility::type_lookup<type_name >::type*)0).operator ,(*(::utility::dummy*)0)) _type_lookup_t
namespace utility
{
struct dummy {};
template <typename T>
struct type_lookup
{
typedef T type;
};
}
'
用法示例:
namespace mpl = bost::mpl;
typedef mpl::vector<T1, T2, T3, T4, T5> storage_types_t;
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::sizeof_<mpl::_1> >
>::type
>::type max_size_t; // type has stored max sizeof(T1, T2, T3, T4, T5)
typedef typename mpl::deref<
typename mpl::max_element<
mpl::transform_view<storage_types_t, mpl::alignof_<mpl::_1> >
>::type
>::type max_alignment_t; // type has stored max alignof(T1, T2, T3, T4, T5)
// testing on real values
UTILITY_TYPE_LOOKUP_BY_ERROR(max_size_t);
UTILITY_TYPE_LOOKUP_BY_ERROR(max_alignment_t);
'
Visual Studio 2015 错误输出:
error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max sizeof here**>' error C2039: ',': is not a member of 'boost::mpl::size_t<**calculated max alignment here**>'