Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard type trait for the value of sizeof(T)

The C++11 standard specifies a type trait std::alignment_of<T> which simply returns the value of alignof(T).

Is there a similar trait for the sizeof operator? Am I just missing it, or was it just missed in the standard, or is there some obscure technical reason why it wasn't specified?

Obviously it is trivial to create such a trait, but I can't imagine it wouldn't have been considered when introducing std::alignment_of.

For context, I have a custom type trait that I use to get the maximum value of a single trait when applied to a list of types.

template <template<class> class Trait, typename F, typename... T>
struct trait_max
  : std::integral_constant<decltype(Trait<F>::value),
      (Trait<F>::value > trait_max<Trait, T...>::value) ? Trait<F>::value : trait_max<Trait, T...>::value>
{ };
template <template<class> class Trait, typename F>
struct trait_max<Trait, F>
  : std::integral_constant<decltype(Trait<F>::value), Trait<F>::value>
{ };

This trait is really handy for when you need know the maximum of a set of types like so:

auto max_align = traits_max<std::alignment_of, int, float, std::string>::value;
auto max_size = traits_max<std::size_of, int, float, std::string>::value; // doesn't exist
like image 609
marack Avatar asked Sep 26 '13 05:09

marack


1 Answers

std::alignment_of isn't new in C++11. It was added (along with the rest of <type_traits>) as part of TR1 in 2007. TR1's <type_traits> was copied wholesale from Boost TypeTraits, which provided alignment_of only because there was no standard way to get at that value in 2005.

Of course in 2005 there was a way to get the size of a type T; it has been spelled sizeof(T) since time immemorial. That's why size_of<T> wasn't in Boost TypeTraits, and that's why it wasn't copied into TR1 in 2007, and that's why it wasn't grandfathered into C++11.

As of 2011, there is also a standard way to get the alignment of a type T; it's spelled alignof(T). The pre-2011 construct std::alignment_of<T>::value is needlessly verbose, and you almost certainly shouldn't be using it anymore unless you're concerned about portability to pre-2011 implementations.

I believe the most idiomatic way of writing your sample code is

size_t max_align = std::max({alignof(int), alignof(float), alignof(std::string)});
size_t max_size = std::max({sizeof(int), sizeof(float), sizeof(std::string)});

Once C++14 rolls around, std::max will become constexpr, so this will be computed at compile-time and be usable in template metaprogramming. But the suckiness of C++11's std::max is a totally separate issue, unrelated to your question. :)

EDIT: Here's a constexpr_max that works in today's C++11. Unfortunately C++11's std::initializer_list can't be used in a constexpr context; C++14 is fixing that too.

template<typename T> constexpr T constexpr_max(T t, T u) {
    return t > u ? t : u;
}

template<typename T, typename... TT> constexpr T constexpr_max(T t, TT... ts) {
    return constexpr_max(t, constexpr_max(ts...));
}
like image 117
Quuxplusone Avatar answered Oct 06 '22 17:10

Quuxplusone