2016-05-12 52 views
6

我的基本想法是從的std ::元組推導出我自己的類來獲得一些輔助類型裏面是這樣的:混亂而來自的std ::元組推導,不能處理的std ::獲得

template <typename ... T> 
class TypeContainer: public std::tuple<T...> 
{ 
    public: 
     using BaseType = std::tuple<T...>; 
     static const size_t Size = sizeof...(T); 
     TypeContainer(T... args):std::tuple<T...>(args...){}; 

     using index_sequence = std::index_sequence_for<T...>; 
}; 

現在我嘗試使用的代碼如下:

using MyType_tuple_with_empty =   std::tuple<  std::tuple<float,int>, std::tuple<>, std::tuple<int>>; 
using MyType_typecontainer_with_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<>, TypeContainer<int>>; 

using MyType_tuple_non_empty =   std::tuple<  std::tuple<float,int>, std::tuple<int>, std::tuple<int>>; 
using MyType_typecontainer_non_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<int>, TypeContainer<int>>; 

template <typename T> 
void Do(const T& parms) 
{ 
    // The following lines result in errors if TypeContainer with 
    // empty element comes in. The empty element is in std::get<1> which 
    // is NOT accessed here! 
    std::cout << std::get<0>(std::get<0>(parms)) << " "; 
    std::cout << std::get<1>(std::get<0>(parms)) << std::endl; 

    std::cout << std::get<0>(std::get<2>(parms)) << std::endl; 
} 


int main() 
{ 
    MyType_tuple_with_empty   p1{{ 1.2,3},{},{1}}; 
    Do(p1); 

    MyType_typecontainer_with_empty p2{{ 1.2,3},{},{1}}; 
    Do(p2); // << this line raise the error 

    MyType_tuple_non_empty   p3{{ 1.2,3},{4},{1}}; 
    Do(p3); 

    MyType_typecontainer_non_empty p4{{ 1.2,3},{4},{1}}; 
    Do(p4); 
} 

如果我Do(p2)編譯我收到以下錯誤:

error: no matching function for call to ' get(const TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> >&) '

有人可以解釋爲什麼存在與std::get有關的空TypeContainer會導致該問題嗎?

編輯: 附加信息:

線條

MyType_tuple_with_empty   p1{{{ 1.2,3},{},{1}}}; 
MyType_tuple_non_empty   p3{{ 1.2,3},{4},{1}}; 

不能gcc5.2.0但gcc6.1.0編譯。這有點神祕,因爲我記得元組的構造函數確實是顯式的。爲什麼這與gcc6.1.0一起使用?但這不是我搜索的問題:-)

另一個提示: 我有問題的代碼似乎與clang3.5.0編譯。

有點費解......

EDIT2: 挖通過錯誤列表(一個漫長的:-)),我發現:

/opt/linux-gnu_5.2.0/include/c++/5.2.0/tuple|832 col 5| note: template argument deduction/substitution failed: main.cpp|104 col 45| note: ' std::tuple<_Elements ...> ' is an ambiguous base class of ' TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> > ' || std::cout << std::get<0>(std::get<0>(parms)) << " " ;

似乎在的libg ++派生有人多次來自任何似乎是破碎庫的元組類型。搜索這個主題帶給我:Empty nested tuples error

這是真的有關嗎?同樣的bug或新的:-)

+0

也許一個[簡化案例](http://coliru.stacked-crooked.com/a/8de00d9fcaa3df1c) –

回答

2

不幸的是,你必須添加的功能,讓你的容器版本:

template <std::size_t I, typename ...T> 
decltype(auto) get(TypeContainer<T...>&& v) 
{ 
    return std::get<I>(static_cast<std::tuple<T...>&&>(v)); 
} 
template <std::size_t I, typename ...T> 
decltype(auto) get(TypeContainer<T...>& v) 
{ 
    return std::get<I>(static_cast<std::tuple<T...>&>(v)); 
} 
template <std::size_t I, typename ...T> 
decltype(auto) get(TypeContainer<T...> const& v) 
{ 
    return std::get<I>(static_cast<std::tuple<T...> const&>(v)); 
} 

,只是使用getstd::getDo種功能。編譯器能夠從參數中選擇命名空間。

我想,我不確定,這是因爲海灣合作委員會有EBO - Empty Base Optimization - 在其元組中實現。什麼是確切的原因是很難猜測的。您可能會考慮在gcc bugzilla中報告此問題。


順便說一句,從STD類派生出來並不是好習慣。如果你從compisition開始,而不是繼承,那麼你需要提供你自己的get函數,並且你不會觀察這個錯誤,節省大量的時間。

+0

現在,我仔細閱讀您的問題... – PiotrNycz

+0

感謝您的回覆。有兩件事我想:首先:訪問一個空元組的元組不應該有不同的行爲,以訪問具有非空元組的元組。第二:鏗鏘作品。我會嘗試你的代碼作爲問題的工作周,但我相信在libg ++中有一個錯誤...另一個。我已經列出了錯誤報告...沒有迴應:-( – Klaus

+0

我幾乎99%肯定這是因爲EBO - 我看着實施 - 有一些模板魔術的事情正在做EBO - 這並不容易閱讀,我沒有時間這樣做,請報告這個,並考慮使用組合CLang可能沒有EBO,或者以更好的方式實現它 – PiotrNycz

相關問題