Гетерогенное хранение переменных-членов параметра класса variadic

У меня есть шаблон класса variadic, который используется для создания класса верхнего уровня для переменного числа классов. Каждый класс, который должен входить в класс верхнего уровня, является производным от базового класса, поскольку для них есть общие функциональные возможности. Я не знаю, как лучше хранить производные классы в родительском классе, но все еще иметь доступ к полной функциональности производного класса.

Если я сохраню переменные аргументы в векторе, они все будут храниться как базовый класс, и я не смогу получить доступ к производным функциям. Если я храню их в кортеже, я не могу понять, как получить доступ к функциям по производному типу. Если я попытаюсь получить к ним доступ как обсуждено здесь на SO тогда make_unique недоступен (C ++ 14?).

Итак, я хочу сделать следующее:

class BaseElement {
public:
virtual int polymorphicFunction() {return 0;};
};

class DerivedElement1 : public BaseElement {
public:
virtual int polymorphicFunction() {return 1;};
}

class DerivedElement2 : public BaseElement {
public:
virtual int polymorphicFunction() {return 2;};
}

template<typename... systems>   // systems will always be of derived class of BaseElement
class System {
System() : subsystems(systems{}...) {} ;  // all variadic elements stored in tuple
// tuple used below, the system elements don't need to be stored in a container, I just want to access them
// I'd be happy to use a vector or access them directly as a member variable
// provided that I can access the derived class.  I can't use RTTI.
const std::tuple<systems...> subSystems;

// pointer or reference, I don't mind, but pd1/2 will always exist,
// (but perhaps be NULL), even if there is no derived element passed to the template parameter
DerivedElement1 *pd1;
DerivedElement2 *pd2;
};

//Desired usage
System<DerivedElement1> sys;  // sys->pd1 == &derivedElement1WithinTuple, sys->pd2 == NULL
System<DerivedElement2> sys;  // sys->pd2 == &derivedElement2WithinTuple, sys->pd2 == NULL
System<DerivedElement1, DerivedElement2> sys;  // sys->pd1 == &derivedElement1WithinTuple, sys->pd1 == &derivedElement1WithinTuple

Кто-нибудь есть какие-либо предложения относительно того, как я мог бы достичь этого, пожалуйста?

0

Решение

С:

#include <cstdint>
#include <type_traits>
#include <tuple>

namespace detail
{

template <typename T, typename... Ts> struct get_index;

template <typename T, typename... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};

template <typename T, typename Tail, typename... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};

template <typename T>
struct get_index<T> : std::integral_constant<std::size_t, 0> {}; // Not foundtemplate <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>& t) noexcept
-> typename std::enable_if<N < sizeof...(Ts), decltype(&std::get<N < sizeof...(Ts) ? N : 0>(t))>::type
{
return &std::get<N>(t);
}

template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>&) noexcept
-> typename std::enable_if<sizeof...(Ts) <= N, nullptr_t>::type
{
return nullptr;
}

}

Ты можешь иметь:

template <typename... systems>
class System {
public:
constexpr System() :
subSystems(),
pd1(detail::safe_get<detail::get_index<DerivedElement1, systems...>::value>(subSystems)),
pd2(detail::safe_get<detail::get_index<DerivedElement2, systems...>::value>(subSystems))
{}

const std::tuple<systems...> subSystems;
const DerivedElement1 *pd1;
const DerivedElement2 *pd2;
};
1

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


По вопросам рекламы [email protected]