2012-01-14 17 views
0

我需要一個通用函數,它可以對容器採用const或非const引用,並將相應的引用返回給按容器限定的元素。沿着這些線路獲取容器中元素的const限定的通用方法

東西:

template <typename C> 
auto get_nth(C& c, int i) -> /* not-sure-what, but let's call it T */ 
{ 
     //.... some tricky code here ... 
} 

我想強調的是,如果C擴展到

SomeContainer const 

那麼T將是

SomeContainer::const_reference 

否則

SomeContainer::reference 

我想我可以把它放在一起使用類型特徵和mtl如果,我的問題是如果有一個更短,更乾淨的方式。

我使用C++ x11(顯然)和提高。

在此先感謝。

+0

如果你傳遞一個右值作爲第一個參數到'get_nth',你想要返回一個左值引用還是右值引用到第i個元素? – fredoverflow 2012-01-14 12:04:17

+0

@FredOverflow我只對左值感興趣。然後正確的事情是使用...(C&C ...)在這種情況下,對嗎? – dsign 2012-01-14 12:16:54

+0

是的。不過,我會更新我的答案:) – fredoverflow 2012-01-14 12:30:01

回答

3

我認爲您在尋找typename C::reference,請參閱23.2.1 [container.requirements.general]§4。


哦,等等,如果C已經const上述不起作用。但是等一下,decltype來救援!

template <typename C> 
auto get_nth(C&& c, int i) -> decltype(*c.begin()) 
{ 
     //.... some tricky code here ... 
} 

如果你也想支持哪個沒有begin成員函數C風格的數組:

#include <iterator> 

template <typename C> 
auto get_nth(C&& c, int i) -> decltype(*std::begin(c)) 
{ 
     //.... some tricky code here ... 
} 

而真正執行不棘手:


請注意,上述解決方案接受左值和rvalues,但它會一直返回一個左值引用。取決於客戶端代碼,這可能是性能問題。看看下面的例子代碼:

std::string s = get_nth(std::vector<std::string> { "hello", "world" }, 0); 

這將結果複製到s,即使移動這將是非常有效的(而且,當然,速度更快)。

爲了解決這個問題,我們需要兩個重載,一個左值和一個右值的爲:

#include <iterator> 
#include <type_traits> 

template <typename C> 
auto get_nth(C& c, int i) -> decltype(*std::begin(c)) 
{ 
    auto it = std::begin(c); 
    std::advance(it, i); 
    return *it; 
} 

template <typename C> 
auto get_nth(C&& c, int i) 
-> typename std::enable_if<std::is_rvalue_reference<C&&>::value, 
          decltype(std::move(*std::begin(c)))>::type 
{ 
    auto it = std::begin(c); 
    std::advance(it, i); 
    return std::move(*it); 
} 

現在的結果將被轉移到senable_if部分是必要的,因爲由於參考摺疊規則,C&&也可以綁定到左值,然後調用初始化s將是不明確的。

+0

謝謝!它沒有我想要的那麼幹淨,但它比我想象的要好得多。 – dsign 2012-01-14 12:01:36

+0

如果只允許ADL的'開始'... :-) – 2012-01-14 14:03:06

+0

@KerrekSB:我知道有人會找到改善某處的機會:) – fredoverflow 2012-01-14 14:46:43

相關問題