2014-07-18 59 views
0

我有一個可變參數類模板,用於爲可變數量的類創建頂級類。每個進入頂級類的類都是從一個基類派生的,因爲它們有共同的功能。我不知道將派生類存儲在父類中的最佳方式,但仍然能夠訪問派生類的全部功能。可變參數成員變量的異構存儲

如果我將可變參數存儲在一個向量中,它們將全部作爲基類存儲,我無法訪問派生的功能。如果我將它們存儲在一個元組中,我無法解決如何通過派生類型訪問函數。如果我嘗試訪問它們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

這是很容易寫'的std ::自己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