Способ 1:
Код: Выделить всё
template
struct foo
{
template
foo(Args&&... args) : m_t(forward(args)...)
{}
T m_t;
}
template
struct foo
{
template
foo(Args&&... args) : m_t(forward(args)...), m_id(0)
{}
T m_t;
int m_id;
};
- Недостаток: повторяющийся код для каждой специализации.
Код: Выделить всё
template
struct foo
{
template
foo(Args&&... args) : m_t(forward(args)...)
{}
virtual ~foo() {}
T m_t;
}
template
struct foo : public foo
{
using foo::foo;
int m_id = 0;
};
- Преимущество: мало кода.
- Недостаток: использование виртуальных таблиц/наследования/и т. д.: больше времени на создание или доступ к членам? Но, с другой стороны, я не претендую на использование «ссылок» на базовый класс. Каковы реальные преимущества и недостатки этого подхода?
Код: Выделить всё
using nil_type = void*;
using zero_type = nil_type[0];
template
struct foo
{
template
foo(Args&&... args) : m_t(forward(args)...), m_int(0)
{}
template
foo(Args&&... args) : m_t(forward(args)...)
{}
T m__t;
typename conditional::type m_int;
};
- Ventages: напишите код один раз; когда with_int имеет значение false, поле m_int имеет размер 0 (почти в gcc 4.7.2).
- Преимущества: больше использования шаблонов (уменьшает читабельность), и я не уверен, как компиляторы справляются с членами размера 0. Я действительно не знаю, в какой степени поле размера 0 опасно или имеет смысл. Повторяющиеся конструкторы, но, возможно, этого можно избежать.
Подробнее здесь: https://stackoverflow.com/questions/154 ... on-members