Determining the largest sizeof () value in a force case

Given:

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

Calculate the following at compile time:

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

I had no idea how to approach this, but this answer clarified how I can start. Using the code in this answer with two types T1and T2, I could use the following in the source file to get the size of a larger object:

size_t largestSize = sizeof(largest<T1, T2>::type);

This is exactly what I would like to do, but I need a template largestfor working with more than two classes - in particular, it will need to check all types stored in the object boost::variant.

I know I boost::varianthave a typestypedef that defines some kind of list of types in a variant. The problem is that I am completely lost when I try to trick all the elements boost::mplinto the implementation. I don’t intuitively understand what it boost::variant::typesis and how I can pass it into my own template that does something with it.

In my head, it will look like the final implementation:

typedef boost::variant<T1, T2, T3, T4> MyVariant;
size_t largestSize = sizeof(largest<MyVariant::types>::type);

Unfortunately, I have no idea how to implement this version largest.

I'm not sure if this is a reasonable approach, so I am open to any other ways to achieve this (maybe apply boost::static_visitorto all types at compile time?).

+4
source share
3

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

++ 14, std::max() constexpr, :

    return variadic_max((a > b ? a : b), cs...);

:

, boost::static_visitor ?

variant - - , variant. .

+7

:

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;

Edit:

boost:: variant, templates, :

template <template <class...> class Var, class... Args>
struct largest<Var<Args...>>: largest<Args...> { };

, . ( , boost:: variant):

cout << sizeof(largest<tuple<int, char, double>>::type) << endl;
+2

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**>'
+1

All Articles