2014-07-18 3 views
0

가변 클래스 수의 최상위 클래스를 만드는 데 사용되는 가변 태그 클래스 템플릿이 있습니다. 최상위 클래스에 포함될 각 클래스는 공통 기능이 있으므로 기본 클래스에서 파생됩니다. 파생 클래스를 상위 클래스에 저장하는 가장 좋은 방법은 모르지만 파생 클래스의 전체 기능에 계속 액세스 할 수는 있습니다.variadic 클래스 매개 변수 멤버 변수의 이기종 저장소

벡터에 variadic args를 저장하면 모두 기본 클래스로 저장되고 파생 된 기능에 액세스 할 수 없습니다. 튜플에 저장하면 파생 된 형식으로 함수에 액세스하는 방법을 찾을 수 없습니다. as discussed here on 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

그것은 표준 : 직접 make_unique''작성하는 매우 간단합니다. '시스템'유형 중 하나의 구성이 포기하지 않는 한 당신은 그것을 필요로하지 않을 수도 있습니다. – Brian

답변

1

:

#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 found 


template <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; 
}; 
+0

완벽 하 고, 대단히 감사합니다! – John

관련 문제