Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining largest sizeof() in boost variant

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 shed some light on how I might get started. Using the code in that answer with two types, T1 and T2, I could use the following in a source file to get the size of the larger object:

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

This is exactly what I'd like to do, but I need the largest template to work with more than two classes - specifically, it would need to check all types stored in a boost::variant object.

I know that boost::variant has a types typedef, which defines some sort of list of types in the variant. The problem is, I get totally lost when I try to wrap my head around all the boost::mpl stuff in the implementation. I don't intuitively understand what boost::variant::types is, and how I might be able to pass it into my own template that does something with it.

In my head, this is what the final implementation might look like:

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

Unfortunately, I have no idea how to go about implementing this version of largest.

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

like image 893
Matt K Avatar asked Dec 24 '22 07:12

Matt K


1 Answers

Just ignore the mpl stuff. Start with:

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

Now max_variant_sizeof<MyVariant>::value will forward all the sizes of all the types to a function. All you need to do is write that 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...);
}

Before C++14, std::max() isn't constexpr, so that can be replaced with:

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

One thing worth noting about:

maybe apply a boost::static_visitor to all types at compile time?

Visitation with a variant is a runtime operation - your visitor gets called with the type that the variant happens to be holding on to. It will not be called with all the types.

like image 170
Barry Avatar answered Dec 28 '22 08:12

Barry