voi*_*ter 3 c++ boost stl compiler-errors boost-bind
我有以下代码:
int MimeDocument::GetAttachmentId( std::string const& content_id )
{
using namespace boost::lambda;
using boost::lambda::_1;
using boost::bind;
int id = 0;
std::vector<std::string>::iterator it =
std::find_if( attachment_list_.begin(), attachment_list_.end(),
bind( &std::string::find, content_id, _1 ) != std::string::npos
);
if( it != attachment_list_.end() ) {
id = std::distance( attachment_list_.begin(), it );
}
return id;
}
Run Code Online (Sandbox Code Playgroud)
在MSVC9 SP1上编译时会导致大量C2780编译器错误.以下是列表顶部的一些内容:
1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<_bi::dm_result<MT::* ,A1>::type,boost::_mfi::dm<M,T>,_bi::list_av_1<A1>::type> boost::bind(M T::* ,A1)' : expects 2 arguments - 3 provided
1> c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind.hpp(1728) : see declaration of 'boost::bind'
1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<Rt2,boost::_mfi::cmf8<R,T,B1,B2,B3,B4,B5,B6,B7,B8>,_bi::list_av_9<A1,A2,A3,A4,A5,A6,A7,A8,A9>::type> boost::bind(boost::type<T>,R (__thiscall T::* )(B1,B2,B3,B4,B5,B6,B7,B8) const,A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 11 arguments - 3 provided
1> c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind_mf2_cc.hpp(223) : see declaration of 'boost::bind'
1>c:\code\work\cmake-mds\server\gmmserver\domino\server\interface\dimime.cpp(210) : error C2780: 'boost::_bi::bind_t<Rt2,boost::_mfi::mf8<R,T,B1,B2,B3,B4,B5,B6,B7,B8>,_bi::list_av_9<A1,A2,A3,A4,A5,A6,A7,A8,A9>::type> boost::bind(boost::type<T>,R (__thiscall T::* )(B1,B2,B3,B4,B5,B6,B7,B8),A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 11 arguments - 3 provided
1> c:\code\work\cmake-mds\build-vc9\third_party\boost\1.48.0\include\boost\bind\bind_mf2_cc.hpp(212) : see declaration of 'boost::bind'
Run Code Online (Sandbox Code Playgroud)
任何与boost相关的编译器错误实际上都是不可读的,对我没有帮助,所以我希望有人可以帮我弄清楚发生了什么.提前致谢.
有四种重载std::string::find:
size_t find(const string& str, size_t pos = 0) const;
size_t find(const char* s, size_t pos, size_t n) const;
size_t find(const char* s, size_t pos = 0) const;
size_t find(char c, size_t pos = 0) const;
Run Code Online (Sandbox Code Playgroud)
因此,必须通过指定地址所采用的特定重载函数来帮助编译器选择一个(解决歧义),例如:
boost::bind( static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find), content_id, _1, 0)
Run Code Online (Sandbox Code Playgroud)
相当难看,不是吗?
注意,在不成功的搜索中std::string::find()返回std::string::npos(通常是size_t(-1)).然后它将转换size_t(-1)为bool(true)并导致std::find_if()返回其第一个参数,无论其余参数是什么.
std::string::find()需要比较的结果std::string::npos.使用boost::bind它看起来像:
// ...
std::vector<std::string>::iterator it = std::find_if(
attachment_list_.begin()
, attachment_list_.end()
, boost::bind(
std::not_equal_to<std::string::size_type>()
, std::string::npos
, boost::bind(
static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find)
, &content_id // pass by pointer, don't copy
, _1
, 0)
)
);
Run Code Online (Sandbox Code Playgroud)
哪个看起来也不太可读.
它可能有点可读性boost::lambda::bind:
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
// ...
std::vector<std::string>::iterator it =
std::find_if(
attachment_list_.begin()
, attachment_list_.end()
, boost::lambda::constant(std::string::npos) != boost::lambda::bind(
static_cast<size_t(std::string::*)(const std::string&, size_t) const>(&std::string::find)
, &content_id // pass by pointer, don't copy
, boost::lambda::_1
, 0
)
);
Run Code Online (Sandbox Code Playgroud)
使用C++ 11 lambda看起来最具可读性和优雅性:
std::vector<std::string>::iterator it = std::find_if(
attachment_list_.begin()
, attachment_list_.end()
, [&content_id](std::string const& i) { return std::string::npos != content_id.find(i); }
);
Run Code Online (Sandbox Code Playgroud)
此外,我注意到id为不成功的搜索返回的是0.它是在第一个元素上搜索成功时返回的相同值.换句话说,此函数的调用者将无法区分不成功的搜索和第一个(第0个)元素匹配时.
在这里使用普通循环进行搜索是最简单和便携的:
std::string* MimeDocument::GetAttachmentId(std::string const& content_id) {
for( std::vector<std::string>::iterator i(attachment_list_.begin()), j(attachment_list_.end())
; i != j
; ++i
) {
if(std::string::npos != content_id.find(*i))
return &*i;
}
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
使用此版本,调用者可以轻松地在成功和不成功的搜索之间进行判断,并在必要时找出匹配的索引:
MimeDocument doc;
// ... populate doc
if(std::string* found = doc.GetAttachmentId("1")) {
// the search was successful.
size_t found_index = found - &doc.attachment_list_.front();
}
Run Code Online (Sandbox Code Playgroud)
所以,选择你的毒药......