I'm trying to make a struct with conditional members, that means, different members exists only with specific specializations. But, I want that this classes are fastest as possible. I've tried it in three differents ways:
Way 1:
template<typename T, bool with_int = false>
struct foo
{
template<typename... Args>
foo(Args&&... args) : m_t(forward<Args>(args)...)
{}
T m_t;
}
template<typename T>
struct foo<T, true>
{
template<typename... Args>
foo(Args&&... args) : m_t(forward<Args>(args)...), m_id(0)
{}
T m_t;
int m_id;
};
- Disadventage: repeated code for each specialization.
Way 2:
template<typename T, bool with_int = false>
struct foo
{
template<typename... Args>
foo(Args&&... args) : m_t(forward<Args>(args)...)
{}
virtual ~foo() {}
T m_t;
}
template<typename T>
struct foo<T, false> : public foo<T>
{
using foo<T>::foo;
int m_id = 0;
};
- Adventage: few code.
- Disadventage: Use of vtables/inheritance/etc: more time in construction or access to members? But, in other way, I don't pretend to to use "references" to base class. What is it the real adventages or disadventages of this aproach?
Way 3
using nil_type = void*;
using zero_type = nil_type[0];
template<typename T, bool with_int = false>
struct foo
{
template<typename... Args, typename = typename enable_if<with_int>::type>
foo(Args&&... args) : m_t(forward<Args>(args)...), m_int(0)
{}
template<typename... Args, typename = typename enable_if<!with_int>::type>
foo(Args&&... args) : m_t(forward<Args>(args)...)
{}
T m__t;
typename conditional<with_int, int, zero_type>::type m_int;
};
- Ventages: Write code once; when
with_int
isfalse
, fieldm_int
has size 0 (almost with gcc 4.7.2). - Adventages: More use of templates (reduce readability) and I'm not sure about how compilers deal with member of size 0. I don't know indeed to what extent a size-0-field is dangerous or has sense. Repeated constructors, but perhaps this is avoidable.
What is the best approach or method?