簡體   English   中英

boost :: transform_iterator不適用於std :: bind(&Pair :: first,_1)嗎?

[英]boost::transform_iterator doesn't work with std::bind( &Pair::first, _1 )?

迭代std::map低谷鍵集的傳統任務使我陷入另一場混亂,在這里似乎還沒有討論過。

簡而言之,此代碼無法編譯(大量使用C ++ 11):

typedef std::pair<int, int> Pair;
vector<Pair> v {Pair(1,2), Pair(2,3)};
using namespace std::placeholders;
auto choose_first = std::bind(&Pair::first, _1);
boost::make_transform_iterator(v.begin(), choose_first);

錯誤信息如下。

no type named 'result_type' in 'struct std::_Bind<std::_Mem_fn<int std::pair<int, int>::*>(std::_Placeholder<1>)>' 

同時,將std::bind更改為boost::bind解決此問題。 但是在我的項目中有一個代碼約定,我們僅使用std::bind

有什么建議怎么辦? (我應該向Boost團隊寫錯誤報告嗎?)

有更好的方法可以遍歷std::map的鍵(或任何value_typepair<T,U>容器)的鍵,即Boost.Rangemap_keys適配器(還有一個map_values ):

#include <boost/range/adaptor/map.hpp>
#include <utility>
#include <vector>
#include <iostream>

int main(){
  typedef std::pair<int, int> Pair;
  std::vector<Pair> v {Pair(1,2), Pair(2,3)};
  for(auto& first : v | boost::adaptors::map_keys){
    std::cout << first << " ";
  }
}

但是回到您的問題:所有Boost庫都使用Boost.Utility函數result_of ,無論出於何種原因它都不會退回到std::result_of ,並且如果不通知decltype如果可用的話,也不會使用decltype #define BOOST_RESULT_OF_USE_DECLTYPE ,您可以將#define BOOST_RESULT_OF_USE_DECLTYPE放在第一個Boost包含之前。

但是,那仍然不能使您的代碼使用Clang 3.1 SVN + libc ++進行編譯。 這是我使用的代碼:

#define BOOST_RESULT_OF_USE_DECLTYPE
#include <boost/iterator/transform_iterator.hpp>
#include <utility>
#include <vector>
#include <functional>

int main(){
  typedef std::pair<int, int> Pair;
  std::vector<Pair> v {Pair(1,2), Pair(2,3)};
  using namespace std::placeholders;
  auto choose_first = std::bind(&Pair::first, _1);
  boost::make_transform_iterator(v.begin(), choose_first);
}

編譯:

clang++ -std=c++0x -stdlib=libc++ -Wall -pedantic -Ipath/to/boost -Wno-mismatched-tags t.cpp

GCC 4.7似乎可以接受,所以我想這是libc ++中的錯誤。

似乎您需要在包含boost庫之前定義BOOST_RESULT_OF_USE_DECLTYPE,以實際使用C ++ 11方法獲取結果類型,而不是依賴於傳統的result_type成員。 這在g ++ 4.6和4.8上可以正常編譯:

#define BOOST_RESULT_OF_USE_DECLTYPE
// ^

#include <vector>
#include <boost/iterator/transform_iterator.hpp>
#include <functional>

int main()
{

typedef std::pair<int, int> Pair;
std::vector<Pair> v {Pair(1,2), Pair(2,3)};
using namespace std::placeholders;
auto choose_first = std::bind(&Pair::first, _1);
boost::make_transform_iterator(v.begin(), choose_first);

}

請參閱討論主題http://lists.boost.org/boost-users/2012/01/72856.php以了解為什么默認情況下未啟用它。


您也可以使用std::mem_fn代替std::bind

auto choose_first = std::mem_fn(&Pair::first);

確實定義了那些舊式類型成員(第2.0.8.10/2節)。 由於std::mem_fn仍然是標准庫的一部分,我相信在您的團隊中使用它沒有問題……?


作為最后的選擇,您總是可以使用C ++ 03的方法來聲明一個函數對象(當然我們知道不推薦使用std::unary_function ):

template <typename T>
struct FirstChooser :
        public std::unary_function<const T&, typename T::first_type>
{
    typename T::first_type operator()(const T& input) const
    {
        return input.first;
    }
};

...

FirstChooser<Pair> choose_first;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM