Static & Template sanity check.
Can people just do a quick sanity check of this concept?
I'm playing around with a technique to parameterise a template with the largest 'sizeof'
result for a set of classes.
A, B, C & D are classes with 1, 2, 3 & 4 members respectively.
e is an instance of E, who's array member is sized according to the largest size of A, B, C or D.
Can anyone think of a way that I may fall foul of the 'Static Initialisation Fiasco' with this setup?
Code:
//*********************************************************
// MaxSizeOf for four parameters.
template <const size_t S1,
const size_t S2,
const size_t S3 = 0,
const size_t S4 = 0>
struct MaxSizeOf
{
static const size_t MAX = MaxSizeOf<MaxSizeOf<S1, S2, S3>::MAX, S4>::MAX;
};
// MaxSizeOf for three parameters.
template <const size_t S1,
const size_t S2,
const size_t S3>
struct MaxSizeOf<S1, S2, S3>
{
static const size_t MAX = MaxSizeOf<MaxSizeOf<S1, S2>::MAX, S3>::MAX;
};
// MaxSizeOf for two parameters.
template <const size_t S1,
const size_t S2>
struct MaxSizeOf<S1, S2>
{
static const size_t MAX = (S1 > S2) ? S1 : S2;
};
//*********************************************************
// Define an A.
struct A
{
int i;
};
// Define a B.
struct B
{
int i;
int j;
};
// Define a C.
struct C
{
int i;
int j;
int k;
};
// Define a D.
struct D
{
int i;
int j;
int k;
int l;
};
// Define a templated E.
template <const size_t SIZE>
struct E
{
char a[SIZE];
};
//*********************************************************
// Declare an instance of an E.
E<MaxSizeOf<sizeof(A), sizeof(B), sizeof(C), sizeof(D)>::MAX> e;
//*********************************************************
int main()
{
size_t size = sizeof(e.a);
return 0;
}
Re: Static & Template sanity check.
Quote:
Originally Posted by
JohnW@Wessex
Can anyone think of a way that I may fall foul of the 'Static Initialisation Fiasco' with this setup?
Since everything seems to be compile-time computed, I don't see where the static initialisation will come into play.
Regards,
Paul McKenzie
Re: Static & Template sanity check.
That's what I thought, but I just got a bit paranoid about missing some dark corner case.
Re: Static & Template sanity check.
seems... elaborate...
why not just:
Code:
template <typename T1, typename T2=char, typename T3=char, typename T4=char> // Add as many T as you want (compiler allowing)
union MaxSizeOf
{
T1 t1;
T2 t2;
T3 t3;
T4 t4;
};
int main()
{
size_t size = sizeof( MaxSizeOf<A,B,C,D> );
return 0;
}
Re: Static & Template sanity check.
Yes that would be simpler.
The technique I used was from a more generic solution for templates with variable numbers of type parameters.
Re: Static & Template sanity check.
C++11 has variadric templates. (=Templates with a variable number of templates)
So you'd have something like
template <typename T, ...>
with the ... being however many parameters the consumer want there to be. Rather than the template designer determining how many parameters there can be.
Re: Static & Template sanity check.
I work with embedded projects and, unfortunately, the compilers aren't likely to have C++11 support for a while yet. :sick:
Re: Static & Template sanity check.
even in pre-c++11, you don't need O(N) specializations (without resorting to union tricks):
Code:
template < bool B, typename T, typename V >
struct conditional { typedef T type; };
template < typename T, typename V >
struct conditional< false, T, V > { typedef V type; };
template < typename T1, typename T2 = void, typename T3 = void, typename T4 = void >
struct biggest_of
{
typedef typename biggest_of<T2,T3,T4>::type BiggestOfOthers;
typedef typename conditional< ( sizeof(T1) >= sizeof(BiggestOfOthers) ),
T1, BiggestOfOthers >::type type;
};
template < typename T1 >
struct biggest_of< T1, void, void, void >
{
typedef T1 type;
};
// char some_array[ sizeof( biggest_of<A,B,C>::type ) ];
with a possible c++11 version being something like:
Code:
#include <type_traits>
template < typename Head, typename... Tail >
struct biggest_of
{
using BiggestOfTail = typename biggest_of<Tail...>::type;
typedef typename std::conditional< ( sizeof(Head) >= sizeof(BiggestOfTail) ),
Head, BiggestOfTail >::type type;
};
template < typename Tail >
struct biggest_of< Tail >
{
typedef Tail type;
};
or if one is interested in the size only:
Code:
template< typename Head >
constexpr std::size_t max_sizeof() { return sizeof(Head); }
template< typename Head, typename Middle, typename... Tail >
constexpr std::size_t max_sizeof() { return sizeof(Head) >= max_sizeof<Middle,Tail...>() ? sizeof(Head) : max_sizeof<Middle,Tail...>(); }
// char some_array[ max_sizeof<A,B,C>() ];
Re: Static & Template sanity check.
Thanks :thumb:
I haven't delved much into TMP yet (It tends to give me a headache quite quickly) but I'll squirrel that information away for future reference.
Re: Static & Template sanity check.
Quote:
Originally Posted by
OReubens
seems... elaborate...
why not just:
Code:
template <typename T1, typename T2=char, typename T3=char, typename T4=char> // Add as many T as you want (compiler allowing)
union MaxSizeOf
{
T1 t1;
T2 t2;
T3 t3;
T4 t4;
};
int main()
{
size_t size = sizeof( MaxSizeOf<A,B,C,D> );
return 0;
}
As I've just discovered, this technique does not compile if any of the template parameters have copy constructors.
On Visual Studio this gives error C2621
Re: Static & Template sanity check.
Quote:
Originally Posted by
JohnW@Wessex
As I've just discovered, this technique does not compile if any of the template parameters have copy constructors.
A union cannot have members that have non-trivial copy constructors.
Why not try this:
http://www.boost.org/doc/libs/1_54_0...l/variant.html
Regards,
Paul McKenzie
Re: Static & Template sanity check.
I ended up using Superbonzo's technique.