C ++ 11: условная компиляция: члены

Я пытаюсь создать структуру с условными членами, то есть разные члены существуют только с конкретными специализациями. Но я хочу, чтобы эти занятия были максимально быстрыми. Я пробовал это тремя разными способами:

Способ 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;
};
  • Недостаток: повторный код для каждой специализации.

Способ 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;
};
  • Преимущество: мало кода.
  • Недостаток: использование виртуальных таблиц / наследование / и т. Д .: больше времени на строительство или доступ к членам? Но, с другой стороны, я не претендую на использование «ссылок» на базовый класс. Каковы же реальные преимущества или недостатки этого подхода?

Способ 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;
};
  • Помещения: напишите код один раз; когда with_int является falseполе m_int имеет размер 0 (почти с gcc 4.7.2).
  • Преимущества: более широкое использование шаблонов (снижение читабельности), и я не уверен в том, как компиляторы работают с элементом размера 0. На самом деле я не знаю, в какой степени поле размера 0 опасно или имеет смысл. Повторные конструкторы, но, возможно, этого можно избежать.

Каков наилучший подход или метод?

3

Решение

Рассматривали ли вы наследство?

template< bool >
struct foo_int_base
{
// stuff without the int
void f(); // does not use m_id
};

template<>
struct foo_int_base< true >
{
// stuff with the int
int m_id = 0;
void f(); // uses m_id
};

template< typename T, bool with_int = false >
struct foo : foo_int_base< with_int >
{
// common stuff here
};
4

Другие решения

Других решений пока нет …