正在确定boost变量中的最大sizeof()

Determining largest sizeof() in boost variant

本文关键字:sizeof boost 变量      更新时间:2023-10-16

给定:

boost::variant<T1,T2,T3,...,TN>

在编译时计算以下内容:

max(sizeof(T1), sizeof(T2), sizeof(T3),... ,sizeof(TN))

我不知道如何处理这个问题,但这个答案让我明白了如何开始。使用该答案中的代码和T1T2两种类型,我可以在源文件中使用以下内容来获得较大对象的大小:

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...);

有一点值得注意:

可能在编译时将boost::static_visitor应用于所有类型?

带有variant的Visitation是一个运行时操作-您的访问者将使用variant碰巧持有的类型进行调用。它不会使用所有类型来调用。

您还可以更改附加到的链接中的代码:

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以及任何其他variadic args模板化类一起工作,只需添加另一个专业化:

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错误输出:

错误C2039:",":不是"boost::mpl::size_t<"的成员**此处计算的最大大小**>'错误C2039:",":不是"boost::mpl::size_t<"的成员**此处计算的最大对齐**>'