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应该在链接选项中有相应的兼容性选择项, 但是无耐我本人不才, 找不到.
还有劳各位大大排忧解难.

非常感谢
...全文
293 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
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));
}
//---------------------------------------------------------------------------
庖丁解牛(侯捷自序) i 目录 v 前言 xvii 本书定位 xvii 合适的读者 xviii 最佳阅读方式 xviii 我所选择的剖析对象 xix 各章主题 xx 编译工具 xx 英术语的运用风格 xxi 英文术语采用原则 xxii 版面字形风格 xxiii 源码形式与下载 xxiv 在线服务 xxvi 推荐读物 xxvi 第1章 stl 概论与版本简介001 1.1 stl 概论 001 1.1.1 stl的历史 003 1.1.2 stl与c++ 标准程序 003 . 1.2 stl 六大组件 - 功能与运用 004 1.3 gnu源码开放精神 007 1.4 hp stl实现版本 009 1.5 p.j. plauger stl实现版本 010 1.6 rouge wave stl实现版本 011 1.7 stlport 实现版本 012 1.8 sgi stl实现版本 总览 013 1.8.1 gnu c++ header 文件分布 014 1.8.2 sgi stl 文件分布与简介 016 stl 标准头文件(无扩展名) 017 c++ 标准规格定案前,hp规范的stl头文件(扩展名 .h) 017 sgi stl 内部文件(sgi stl真正实现于此) 018 1.8.3 sgi stl 的组态设定(configuration) 019 1.9可能令你困惑的c++ 语法 026 1.9.1 stl_config.h 的各种组态 027 组态3:static template member 027 组态5:class template partial specialization 028 组态6:function template partial order 028 组态7:explicit function template arguments 029 组态8:member templates 029 组态10:default template argument depend on previous template parameters 030 组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部直接初始化 037 in-class static const integral data member initialization 1.9.4 increment/decrement/dereference 运算子 037 1.9.5 "前闭后开"区间表示法 [ ) 039 1.9.6 function call运算子(operator()) 040 第2章 空间配置器(allocator) 043 2.1 空间配置器的标准接口 043 2.1.1 设计一个简单的空间配置器,jj::allocator 044 2.2 具备次配置力(sub-allocation)的sgi 空间配置器 047 2.2.1 sgi 标准的空间配置器,std::allocator 047 2.2.2 sgi 特殊的空间配置器,std::alloc 049 2.2.3 构造和析构基本工具:construct() 和 destroy() 051 2.2.4 空间的配置与释放,std::alloc 053 2.2.5 第一级配置器 __malloc_alloc_template 剖析 056 2.2.6 第二级配置器 __default_alloc_template剖析 059 2.2.7 空间配置函数allocate() 062 2.2.8 空间释放函数deallocate() 064 2.2.9 重新充填free-lists 065 2.2.10 内存池(memory pool) 066 2.3 内存基本处理工具 070 2.3.1 uninitialized_copy 070 2.3.2 uninitialized_fill 071 2.3.3 uninitialized_fill_n 071 第3章 迭代器(iterators)概念与 traits 编程技法 079 3.1 迭代器设计思维 - stl关键所在 079 3.2 迭代器是一种 smart pointer 080 3.3 迭代器相应型别(associated types) 084 3.4 traits 编程技法 - stl源码门钥 085 partial specialzation(偏特化)的意义 086 3.4.1 迭代器相应型别之一value_type 090 3.4.2 迭代器相应型别之二difference_type 090 3.4.3 迭代器相应型别之三pointer_type 091 3.4.4 迭代器相应型别之四reference_type 091 3.4.5 迭代器相应型别之五iterator_category 092 以advanced() 为例 093 消除 "单纯传递调用函数" 097 以distance() 为例 098 3.5 std::iterator class 的保证 099 3.6 iterator相关源码完整重列 101 3.7 sgi stl的私房菜:__type_traits 103 第4章 序列式容器(sequence containers) 113 4.1 容器概观与分类 113 4.1.1 序列式容器(sequence containers) 114 4.2 vector 115 4.2.1 vector 概述 115 4.2.2 vector 定义摘要 115 4.2.3 vector 的迭代器 117 4.2.4 vector 的数据结构 118 4.2.5 vector 的构造与内存管理:constructor, push_back 119 4.2.6 vector 的元素操作:pop_back, erase, clear, insert 123 4.3 list 128 4.3.1 list 概述 128 4.3.2 list 的节点(node) 129 4.3.3 list 的迭代器 129 4.3.4 list 的数据结构 131 4.3.5 list 的构造与内存管理:constructor, push_back, insert 132 4.3.6 list 的元素操作:push_front, push_back, erase, pop_front, 136 pop_back, clear, remove, unique, splice, merge, reverse, sort 4.4 deque 143 4.4.1 deque 概述 143 4.4.2 deque 的控器 144 4.4.3 deque 的迭代器 146 4.4.4 deque 的数据结构 150 4.4.5 deque 的构造与内存管理 :ctor, push_back, push_front 152 4.4.6 deque 的元素操作:pop_back, pop_front, clear, erase, insert 161 4.5 stack 167 4.5.1 stack 概述 167 4.5.2 stack 定义式完整列表 167 4.5.3 stack 没有迭代器 168 4.5.4 以list 做为stack 的底层容器 168 4.6 queue 169 4.6.1 queue 概述 169 4.6.2 queue 定义式完整列表 170 4.6.3 queue 没有迭代器 171 4.6.4 以list 做为queue 的底层容器 171 4.7 heap(隐式表述,implicit representation) 172 4.7.1 heap 概述 172 4.7.2 heap 算法 174 push_heap 174 pop_heap 176 sort_heap 178 make_heap 180 4.7.3 heap 没有迭代器 181 4.7.4 heap 测试实例 181 4.8 priority-queue 183 4.8.1 priority-queue 概述 183 4.8.2 priority-queue 定义式完整列表 183 4.8.3 priority-queue 没有迭代器 185 4.8.4 priority-queue 测试实例 185 4.9 slist 186 4.9.1 slist 概述 186 4.9.2 slist 的节点 186 4.9.3 slist 的迭代器 188 4.9.4 slist 的数据结构 190 4.9.5 slist 的元素操作 191 第5章 关联式容器(associated containers) 197 5.1 树的导览 199 5.1.1 二元搜寻树(binary search tree) 200 5.1.2 平衡二元搜寻树(balanced binary search tree) 203 5.1.3 avl tree(adelson-velskii-landis tree) 203 5.1.4 单旋转(single rotation) 205 5.1.5 双旋转(double rotation) 206 5.2 rb-tree(红黑树) 208 5.2.1 插入节点 209 5.2.2 一个由上而下的程序 212 5.2.3 rb-tree 的节点设计 213 5.2.4 rb-tree 的迭代器 214 5.2.5 rb-tree 的数据结构 218 5.2.6 rb-tree 的构造与内存管理 221 5.2.7 rb-tree 的元素操作 223 元素插入动作 insert_equal 223 元素插入动作 insert_unique 224 真正的插入执行程序 __insert 224 调整rb-tree(旋转及改变颜色) 225 元素的搜寻 find 229 5.3 set 233 5.4 map 237 5.5 multiset 245 5.6 multimap 246 5.7 hashtable 247 5.7.1 hashtable 概述 247 线性探测(linear probing) 249 二次探测(quadratic probing) 251 分离链(separate chaining) 253 5.7.2 hashtable 的桶子(buckets)与节点(nodes) 253 5.7.3 hashtable 的迭代器 254 5.7.4 hashtable 的数据结构 256 5.7.5 hashtable 的构造与内存管理 258 插入动作(insert)与表格重整(resize) 259 判知元素的落脚处(bkt_num) 262 复制(copy_from)和整体删除(clear) 263 5.7.6 hashtable 运用实例(find, count) 264 5.7.7 hash functions 268 5.8 hash_set 270 5.9 hash_map 275 5.10 hash_multiset 279 5.11 hash_multimap 282 第6章 算法(algorithms) 285 6.1 算法概观 285 6.1.1 算法分析与复杂度表示 o( ) 286 6.1.2 stl算法总览 288 6.1.3 mutating algorithms - 会改变操作对象之值 291 6.1.4 nonmutating algorithms - 不改变操作对象之值 292 6.1.5 stl算法的一般形式 292 6.2 算法的泛化过程 294 6.3 数值算法 [stl_numeric.h] 298 6.3.1 运用实例 298 6.3.2 accumulate 299 6.3.3 adjacent_difference 300 6.3.4 inner_product 301 6.3.5 partial_sum 303 6.3.6 power 304 6.3.7 itoa 305 6.4 基本算法 [stl_algobase.h] 305 6.4.1 运用实例 305 6.4.2 equal 307 fill 308 fill_n 308 iter_swap 309 lexicographical_compare 310 max, min 312 mismatch 313 swap 314 6.4.3 copy,强化效率无所不用其极 314 6.4.4 copy_backward 326 6.5 set 相关算法(应用于有序区间) 328 6.5.1 set_union 331 6.5.2 set_intersection 333 6.5.3 set_difference 334 6.5.4 set_symmetric_difference 336 6.6 heap算法:make_heap, pop_heap, push_heap, sort_heap 338 6.7 其它算法 338 6.7.1 单纯的数据处理 338 adjacent_find 343 count 344 count_if 344 find 345 find_if 345 find_end 345 find_first_of 348 for_each 348 generate 349 generate_n 349 includes (应用于有序区间) 349 max_element 352 merge (应用于有序区间) 352 min_element 354 partition 354 remove 357 remove_copy 357 remove_if 357 remove_copy_if 358 replace 359 replace_copy 359 replace_if 359 replace_copy_if 360 reverse 360 reverse_copy 361 rotate 361 rotate_copy 365 search 365 search_n 366 swap_ranges 369 transform 369 unique 370 unique_copy 371 6.7.2 lower_bound (应用于有序区间) 375 6.7.3 upper_bound (应用于有序区间) 377 6.7.4 binary_search (应用于有序区间) 379 6.7.5 next_permutation 380 6.7.6 prev_permutation 382 6.7.7 random_shuffle 383 6.7.8 partial_sort / partial_sort_copy 386 6.7.9 sort 389 6.7.10 equal_range(应用于有序区间) 400 6.7.11 inplace_merge(应用于有序区间) 403 6.7.12 nth_element 409 6.7.13 merge sort 411 第7章 仿函数(functor,另名 函数对象function objects) 413 7.1 仿函数(functor)概观 413 7.2 可配接(adaptable)的关键 415 7.2.1 unary_function 416 7.2.2 binary_function 417 7.3 算术类(arithmetic)仿函数 418 plus, minus, multiplies, divides, modulus, negate, identity_element 7.4 关系类(relational)仿函数 420 equal_to, not_equal_to, greater, greater_equal, less, less_equal 7.5 逻辑运算类(logical)仿函数 422 logical_and, logical_or, logical_not 7.6 证同(identity)、选择(select)、投射(project) 423 identity, select1st, select2nd, project1st, project2nd 第8章 配接器(adapter) 425 8.1 配接器之概观与分类 425 8.1.1 应用于容器,container adapters 425 8.1.2 应用于迭代器,iterator adapters 425 运用实例 427 8.1.3 应用于仿函数,functor adapters 428 运用实例 429 8.2 container adapters 434 8.2.1 stack 434 8.2.2 queue 434 8.3 iterator adapters 435 8.3.1 insert iterators 435 8.3.2 reverse iterators 437 8.3.3 stream iterators (istream_iterator, ostream_iterator) 442 8.4 function adapters 448 8.4.1 对传回值进行逻辑否定:not1, not2 450 8.4.2 对参数进行系结(绑定):bind1st, bind2nd 451 8.4.3 用于函数合成:compose1, compose2(未纳入标准) 453 8.4.4 用于函数指针:ptr_fun 454 8.4.5 用于成员函数指针:mem_fun, mem_fun_ref 456 附录a 参考资料与推荐读物(bibliography) 461 附录b 侯捷网站简介 471 附录c stlport 的移植经验(by 孟岩) 473 borland c++builder 5 474 microsoft visual c++ 6.0 477 索引 481

13,871

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧