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
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...));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With