[英]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_type
為pair<T,U>
容器)的鍵,即Boost.Range的map_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.