标签:std function .. reference int wrapper Tp __ tr1
一、问题 在常规的函数调用中,通常是直接看到函数的定义并调用该函数,所以,函数调用传递的是值还是引用是根据函数声明来决定的。但是,在std::tr1中的bind函数本身是为了完成不同格式参数的适配,所以函数调用处看到的内容和真正的函数执行位置看到的内容并不相同。 简单的说,这里可以简单的模拟下bind的实现方法 tsecer@harry: cat tr1_ref.cpp template<typename T, typename F> int foo(F f, T t) { return f(t); } typedef int(*funtype)(int &, int); struct adaptor { funtype m_fun; int m_arg; adaptor(funtype f, int y) :m_fun(f), m_arg(y) {} int operator()(int x) { return m_fun(x, m_arg); } }; int bar(int &x, int y) { return x + y; } int main() { int x =1, y =2; adaptor a(bar, y); foo(a, x); } tsecer@harry: g++ tr1_ref.cpp tsecer@harry: 在上面的例子中,adaptor a(bar, y) 语句生成的局部变量就相当于是 tr1::bind生成的中间变量类型,可以看到的是,虽然bar函数声明自己的第一个参数是一个引用类型,但是在adaptor类中,它依然只是把它作为一个值保存起来,进而在调用bar函数的时候,传入的是一个复制的值而不是引用,所以导致最终并不是希望的结果。 二、gcc的std库如何解决这个问题 1、引入特殊ref类型 template<typename _Tp> class reference_wrapper : public _Reference_wrapper_base<typename remove_cv<_Tp>::type> { // If _Tp is a function type, we can't form result_of<_Tp(...)>, // so turn it into a function pointer type. typedef typename _Function_to_function_pointer<_Tp>::type _M_func_type; _Tp* _M_data; public: typedef _Tp type; explicit reference_wrapper(_Tp& __indata): _M_data(&__indata) { } reference_wrapper(const reference_wrapper<_Tp>& __inref): _M_data(__inref._M_data) { } reference_wrapper& operator=(const reference_wrapper<_Tp>& __inref) { _M_data = __inref._M_data; return *this; } operator _Tp&() const { return this->get(); } _Tp& get() const { return *_M_data; } #define _GLIBCXX_REPEAT_HEADER <tr1/ref_wrap_iterate.h> #include <tr1/repeat.h> #undef _GLIBCXX_REPEAT_HEADER }; // Denotes a reference should be taken to a variable. template<typename _Tp> inline reference_wrapper<_Tp> ref(_Tp& __t) { return reference_wrapper<_Tp>(__t); } 在其基类reference_wrapper中,其拷贝构造函数有一个这样的声明 typedef _Tp type; explicit reference_wrapper(_Tp& __indata): _M_data(&__indata) { } 也就是用匹配类型给变量初始化的时候,把其地址保存在自己的_M_data中,而不是保存自己独立的一份数据,所以可以达到引用的效果。 2、在参数提取中 特例化参数为reference_wrapper类型的_Mu模版,从而在参数提取时调用__arg.get(),这个时候就可以返回引用类型。 gcc-4.1.0\libstdc++-v3\include\tr1\functional template<typename _Arg, bool _IsBindExp = is_bind_expression<_Arg>::value, bool _IsPlaceholder = (is_placeholder<_Arg>::value > 0)> class _Mu; /** * @if maint * If the argument is reference_wrapper<_Tp>, returns the * underlying reference. [TR1 3.6.3/5 bullet 1] * @endif */ template<typename _Tp> class _Mu<reference_wrapper<_Tp>, false, false> { public: typedef _Tp& result_type; /* Note: This won't actually work for const volatile * reference_wrappers, because reference_wrapper::get() is const * but not volatile-qualified. This might be a defect in the TR. */ template<typename _CVRef, typename _Tuple> result_type operator()(_CVRef& __arg, const _Tuple&) const volatile { return __arg.get(); } }; 三、使用tr1库看下效果 可以看到,如果不使用 tr1::ref封装x,那么虽然bind的函数参数使用的是引用,但是最终的结果依然没有修改到传入的参数x。 tsecer@harry: cat usetr1.cpp #include <tr1/functional> #include <stdio.h> using namespace std; typedef tr1::function<void(int &)> ff; void foo(int &x) { x *= 10; } int main() { int x = 1; tr1::bind(foo, x)(); printf("x %d\n", x); tr1::bind(foo, tr1::ref(x))(); printf("x %d\n", x); } tsecer@harry: g++ usetr1.cpp tsecer@harry: ./a.out x 1 x 10
标签:std,function,..,reference,int,wrapper,Tp,__,tr1 来源: https://www.cnblogs.com/tsecer/p/10488041.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。