我認爲您在尋找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);
}
現在的結果將被轉移到s
。 enable_if
部分是必要的,因爲由於參考摺疊規則,C&&
也可以綁定到左值,然後調用初始化s
將是不明確的。
如果你傳遞一個右值作爲第一個參數到'get_nth',你想要返回一個左值引用還是右值引用到第i個元素? – fredoverflow 2012-01-14 12:04:17
@FredOverflow我只對左值感興趣。然後正確的事情是使用...(C&C ...)在這種情況下,對嗎? – dsign 2012-01-14 12:16:54
是的。不過,我會更新我的答案:) – fredoverflow 2012-01-14 12:30:01