2015-09-07 81 views
2

這裏是一個遞歸類定義:獲取給定參數可變類的成員由類型

template<class... T> 
class Mgr2 
{ 

}; 

template<class T, class... args> 
class Mgr2<T, args...> 
{ 
    Container<T> _container; 
    Mgr2<args...> _tail; 
public: 
    Mgr2() { }; 
}; 

我想實現如下:

Mgr2<int, double> mgr; 
mgr.get<int>(); // retrieves the Container<int> element 

我怎麼能這樣做?我試圖做幾件事情,但失敗....一個免費的功能也很好,我不在乎如果行爲是不確定的,如果類中定義了2個「int」,例如

謝謝!

+5

如果庫支持新的C++ 14 ['GET'](http://en.cppreference.com/w/cpp/utility/tuple/get),你可以直接使用'std :: tuple'或者將它們合成到你的'Mgr2'類中。 – user657267

回答

1

這裏的一種方式的草圖要做到這一點,通過重組Mgr2

template<class T> 
struct Leaf { 
    Container<T> container; 
}; 

template<class... Ts> 
struct Mgr2 : Leaf<Ts>... {  
    template<class T> 
    Container<T> &get() { 
     return static_cast<Leaf<T>&>(*this).container; 
    } 
}; 

有重複的類型,只要Mgr2被實例化導致編譯時錯誤。


如果我們想在除了由類型索引的整數允許重複,或索引,我們可以將索引參數添加到Leaf

template<std::size_t I, class T> 
struct Leaf { 
    Container<T> container; 
}; 

和調整Mgr2

template<class Seq, class...> struct Mgr2_Impl; 

template<std::size_t... Is, class... Ts> 
struct Mgr2_Impl<std::index_sequence<Is...>, Ts...> 
    : Leaf<Is, Ts>... { }; 

template<class... Ts> 
struct Mgr2 : Mgr2_Impl<std::index_sequence_for<Ts...>, Ts...> { 
private: 
    template<class T, std::size_t I> 
    Leaf<I, T>& do_get(Leaf<I, T>& leaf) { return leaf; } 
    template<std::size_t I, class T> 
    Leaf<I, T>& do_get(Leaf<I, T>& leaf) { return leaf; } 

public: 
    template<class T> 
    decltype(auto) get() { return do_get<T>(*this).container; } 
    template<std::size_t I> 
    decltype(auto) get() { return do_get<I>(*this).container; } 
}; 

如果你想保留你的原始設計,你可以使用SFINAE或標籤發送。顯示前:

template<class U> 
std::enable_if_t<std::is_same<U, T>{}, Container<U>&> get(){ 
    return _container; 
} 
template<class U> 
std::enable_if_t<!std::is_same<U, T>{}, Container<U>&> get(){ 
    return _tail.template get<U>(); 
} 
1

隨着std::tuple,並std::get從C++ 14:

template<typename... Ts> 
class Mgr2 
{ 
private: 
    std::tuple<Container<Ts>...> _containers; 
public: 
    Mgr2() {}; 

    template <typename T> 
    const Container<T>& get() const { return std::get<Container<T>>(_containers); } 

    template <typename T> 
    Container<T>& get() { return std::get<Container<T>>(_containers); } 
}; 

Demo

如果你堅持使用C++ 11,你可以在C++ 11中編寫你自己的get<T>

0

我只是發現它可以這樣很容易做到:

template<class... T> 
class CptMgr 
{ 
}; 

template<class T, class... args> 
class CptMgr<T, args...> 
{ 
    CptContainer<T> _container; 
    CptMgr<args...> _tail; 

public: 
    template<class U> 
    CptContainer<U>& get() { return _tail.get<U>(); }; 

    template<> 
    CptContainer<T>& get() { return _container; }; 
} 
+0

您正在使用MSVC,不是嗎?此代碼以多種方式中斷。 –

+0

是的,我怎麼這樣? – lezebulon