• 主页
  • Windows SDK/API
  • 基础类
  • ActiveX
  • 数据库及相关技术
  • 网络及通讯开发
  • VCL组件使用和开发

C++BUILDER 2009 中的 STL 库的 std::bind2nd的问题

morphia 2008-12-22 11:45:27
一个简单的C++使用STL的算法问题:
我有一个函数子 ObjectEqualID, 带入两参数, 结合 std::remove_if使用,需要使用std::bind2nd来绑定第二个参数,于是有以下的代码:



#include <functional>
#include <algorithm>

struct ObjectEqualID : public std::binary_function<Object, DWORD, bool>
{
bool operator ()(Object const& obj, DWORD dwObjID) const
{
return obj.GetObjID() == dwObjID;
}
};

Object_Iter p = std::remove_if(objs.begin(), objs.end(), std::bind2nd(ObjectEqualID(), dwObjID));



但是这段代码remove_if那一行怎么样都没有办法编译通过, 出现链接错误:
[TASM32 Error] AutoThread.asm(7735): Undefined symbol: @@std@%remove_copy_if$55std@%_Vector_iterator$6Object23std@%allocator$6Object%%t131std@%binder2nd$13ObjectEqualID%%$q55std@%_Vector_iterator$6Object23std@%allocator$6Object%%t1t131std@%binder2nd$13ObjectEqualID%$55std@%_Vector_itera1elpYZsgy

头文件已经正确加入, 后来经排除法(我换上了一个参数的函数子)后,发现是std::bind2nd有问题,于是自己操刀写了一个bind2nd, 链接正确通过, 并且成功, 百思不得其解, 今天整理代码,想把自己写的bind2nd整理至std2这个命名空间中, 居然发现同样的问题又出现了. 这回让我很头大, 因为这表明这个问题是和编译器有问题, 而不是因为STL中文件缺失或其它非编译器问题. 把bind2nd的命名空间去掉, 编译链接一切又正常.

为了让各位确定不是自己写的bind2nd的问题, 现把bind2nd的代码奉上:



template <typename _Pr_>
class binder2nd : public std::unary_function<typename _Pr_::first_argument_type,
typename _Pr_::result_type>
{
public:
binder2nd(_Pr_ pr, _Pr_::second_argument_type value2nd)
: m_pr(pr)
, m_value2nd(value2nd)
{

}

_Pr_::result_type operator ()(_Pr_::first_argument_type value) const
{
return m_pr(value, m_value2nd);
}

private:
_Pr_ m_pr;
_Pr_::second_argument_type m_value2nd;
};

template <typename _Pr_>
binder2nd<_Pr_> bind2nd(_Pr_ pr, typename _Pr_::second_argument_type value)
{
return binder2nd<_Pr_>(pr, value);
}



我现在预想最好的结果是, BCB应该在链接选项中有相应的兼容性选择项, 但是无耐我本人不才, 找不到.
还有劳各位大大排忧解难.

非常感谢
...全文
207 点赞 收藏 5
写回复
5 条回复
morphia 2008年12月23日
谢谢楼上各位, 因为我以前一直用VC++, 所以还不是很习惯BCB的C++编译器, 看了楼上各位的回复后突然想到是不是因为我把所有的函数都放到头文件中的缘故, 因为我的那个包含有remove_if的函数是个static的, 然后我将其移动至.cpp文件中后, 编译通过了..!

to: jxw1987628
谢谢你提出我的bind2nd的问题, 我翻了一下stl的源代码, 的确和你说的是一样, 虽然我那样写不会导致有太多的问题, 不过还是非常感谢你, 在以后C++编程中我会注意的.

结贴啦.
回复 点赞
jxw1987628 2008年12月23日
/*
我在BCB 6.0中测试你上面的调用是可行的(可正常通过编译连接),就是你那个调用STL库的bind2nd

是可行的,不知道你后面是不是自己写了1个binder2nd类模板的代码,我看了下,对于你自己写的binder2nd

类模板的代码中的bind2nd 函数模板的实现部分是有问题的。

我将其该为如下也是可以通过编译连接。


*/

namespace MySpace
{
template <typename _Pr_>
class binder2nd : public std::unary_function<typename _Pr_::first_argument_type,
typename _Pr_::result_type>
{
public:
binder2nd(_Pr_ pr, _Pr_::second_argument_type value2nd)
: m_pr(pr)
, m_value2nd(value2nd)
{

}

_Pr_::result_type operator ()(_Pr_::first_argument_type value) const
{
return m_pr(value, m_value2nd);
}

private:
_Pr_ m_pr;
_Pr_::second_argument_type m_value2nd;
};

/* 这个是我修改后的
template <typename _Pr_,typename _Tp>
inline binder2nd<_Pr_>
bind2nd(const _Pr_& pr, const _Tp& __x)
{
typedef typename _Pr_::second_argument_type _Arg2_type ;
return binder2nd<_Pr_>(pr, _Arg2_type(__x));
}
*/

//这个是你原来自己的
template <typename _Pr_>
binder2nd<_Pr_> bind2nd(_Pr_ pr, typename _Pr_::second_argument_type value)
{
return binder2nd<_Pr_>(pr, value);
}

}

std::remove_if(objs.begin(), objs.end(),MySpace::bind2nd(ObjectEqualID(), dwObjID));
回复 点赞
我来看看CB 2008年12月23日
还是兼容性问题。
回复 点赞
痞子酷 2008年12月23日
Unix下测试没有问题:
template <class Operation>
class binder1st : public unary_function<typename
Operation::second_argument_type,
typename Operation::result_type> ;

template <class Operation, class T>
binder1st<Operation> bind1st (const Operation&, const T&);

template <class Operation>
class binder2nd : public unary_function<typename
Operation::first_argument_type,
typename Operation::result_type> ;

template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation&, const T&);

DESCRIPTION
Because so many functions provided by the standard library take other
functions as arguments, the library includes classes that let you
build new function objects out of old ones. Both bind1st() and
bind2nd() are functions that take as arguments a binary function
object f and a value x, and return, respectively, classes binder1st
and binder2nd. The underlying function object must be a subclass of
binary_function.

Class binder1st binds the value to the first argument of the binary
function, and binder2nd does the same thing for the second argument of
the function. The resulting classes can be used in place of a unary
predicate in other function calls.

For example, you could use the count_if algorithm to count all
elements in a vector that are less than or equal to 7, using the
following:

count_if (v.begin, v.end, bind1st(greater<int> (),7), littleNums)

This function adds one to littleNums each time the predicate is true,
i.e., each time 7 is greater than the element.

INTERFACE
// Class binder1st

template <class Operation>
class binder1st
: public unary_function<typename
Operation::second_argument_type,
typename Operation::result_type>
{
public:

typedef typename unary_function<typename
Operation::second_argument_type, typename
Operation::result_type>::argument_type argument_type;
typedef typename unary_function<typename
Operation::second_argument_type, typename
Operation::result_type>::result_type result_type;

binder1st(const Operation&,
const typename Operation::first_argument_type&);
result_type operator() (const argument_type&) const;
};

// Class binder2nd
template <class Operation>
class binder2nd
: public unary_function<typename
Operation::first_argument_type,
typename Operation::result_type>
{
public:
typedef typename unary_function<typename
Operation::first_argument_type, typename
Operation::result_type>::argument_type argument_type;
typedef typename unary_function<typename
Operation::first_argument_type, typename
Operation::result_type>::result_type result_type;

binder2nd(const Operation&,
const typename Operation::second_argument_type&);

- 2 - Formatted: December 23, 2008

bind1st(3C++) Rogue Wave Software bind1st(3C++)
- -

20 Mar 1996

result_type operator() (const argument_type&) const;
};

// Creator bind1st

template <class Operation, class T>
binder1st<Operation> bind1st (const Operation&, const T&);

// Creator bind2nd

template<class Operation, class T>
binder2nd <Operation> bind2nd(const Operation&, const T&);

EXAMPLE
//

// binders.cpp
//
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream.h>
int main()
{
typedef vector<int>::iterator iterator;
int d1[4] = {1,2,3,4};
//
// Set up a vector
//
vector<int> v1(d1,d1 + 4);
//
// Create an 'equal to 3' unary predicate by binding 3 to
// the equal_to binary predicate.
//
binder1st<equal_to<int> > equal_to_3 =
bind1st(equal_to<int>(),3);
//
// Now use this new predicate in a call to find_if
//
iterator it1 = find_if(v1.begin(),v1.end(),equal_to_3);
//
// Even better, construct the new predicate on the fly
//
iterator it2 =
find_if(v1.begin(),v1.end(),bind1st(equal_to<int>(),3));
//
// And now the same thing using bind2nd 20 Mar 1996

// Same result since == is commutative
//
iterator it3 =
find_if(v1.begin(),v1.end(),bind2nd(equal_to<int>(),3));
//
// it3 = v1.begin() + 2
//
// Output results
//
cout << *it1 << " " << *it2 << " " << *it3 << endl;
return 0;
}

Output : 3 3 3
回复 点赞
Waiting4you 2008年12月23日
你用的是什么版本?我在BCB2009 Update2上试了没出错。

struct Object{
DWORD GetObjID() const
{
return 0;
}
};

struct ObjectEqualID : public std::binary_function<Object &, DWORD, bool>
{
bool operator ()(Object const& obj, DWORD dwObjID) const
{
return obj.GetObjID() == dwObjID;
}
};

void __fastcall TForm1::FormCreate(TObject *Sender)
{
typedef std::vector<Object> vec_objs;
typedef vec_objs::iterator Object_Iter;
DWORD dwObjID = 0;
vec_objs objs;

//bool bt = std::bind2nd(ObjectEqualID(), dwObjID)( Object() );

Object_Iter p = std::remove_if(objs.begin(), objs.end(), std::bind2nd(ObjectEqualID(), dwObjID));
}
//---------------------------------------------------------------------------
回复 点赞
发动态
发帖子
C++ Builder
创建于2007-08-02

2563

社区成员

10.2w+

社区内容

C++ Builder相关内容讨论区
社区公告
暂无公告