2014-11-17 100 views
1

我寫了一個方便的functor包裝元組std :: get。當用boost轉換器和運算符[]使用它時,我會收到警告,我正在返回對本地臨時對象的引用。我的系統:ubuntu 14.04,編譯器:clang-3.5和g ++ - 4.8.2,boost版本:1.56。boost ::用元組仿函數轉換給出奇怪的警告

#include <boost/range/adaptor/transformed.hpp> 

#include <utility> 
#include <vector> 

template <std::size_t I> 
struct tuple_get { 
    template <typename Tuple> 
    auto operator()(Tuple &&tuple) const -> 
      decltype(std::get<I>(std::forward<Tuple>(tuple))) { 
     return std::get<I>(std::forward<Tuple>(tuple)); 
    } 
}; 

int main() { 
    //removing const gets rid of warning 
    const std::vector<std::tuple<int,int>> v = {std::make_tuple(0, 0)}; 
    //gives warning 
    (v | boost::adaptors::transformed(tuple_get<0>{})) [0]; 
} 

警告信息:

include/boost/range/iterator_range_core.hpp:390:16: warning: returning reference to local temporary object [-Wreturn-stack-address] 
    return this->m_Begin[at]; 
note: in instantiation of member function 'boost::iterator_range_detail::iterator_range_base<boost::transform_iterator<tuple_get<0>, 
    std::__1::__wrap_iter<const std::__1::tuple<int, int> *>, boost::use_default, boost::use_default>, boost::random_access_traversal_tag>::operator[]' requested here 
(v | boost::adaptors::transformed(tuple_get<0>{})) [0]; 

添加-Wreturn標誌堆棧地址是不是一個解決方案,因爲它在更大的項目危險。

我注意到,刪除const關鍵字擺脫了警告,但我不知道爲什麼,也不想假設functor只獲取非const範圍。

問題:如何修復代碼以擺脫警告?爲什麼刪除const會擺脫警告?

+0

適用於boost 1.55和g ++ - 4.8.2。 – ForEveR

+1

@ForEveR我也注意到了。我專門下載了boost 1.56來重新測試:) – sehe

回答

2

這是真的。

// 
// When storing transform iterators, operator[]() 
// fails because it returns by reference. Therefore 
// operator()() is provided for these cases. 
// 

所以,你應該能夠與

(v | boost::adaptors::transformed(tuple_get<0>{})) (0); 

它返回abstract_value_type(這是僅當元件是抽象的,陣列或功能,否則VALUE_TYPE基準)固定。

+0

Bah,你打敗了我。 – Bulletmagnet

+0

@sehe所以這是一個使用operator []的bug?爲什麼沒有const沒有警告? –

+0

是的。我覺得很難解釋。但是,本標準提案中描述了一些內容:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4221.pdf。 §2.3通用觀察下的樣本與本文非常相似。 – sehe