首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于函数指针与类作模板参数的类型推导有关问题

2013-08-13 
关于函数指针与类作模板参数的类型推导问题本帖最后由 shun01 于 2013-08-10 10:53:44 编辑今天仿STL func

关于函数指针与类作模板参数的类型推导问题
本帖最后由 shun01 于 2013-08-10 10:53:44 编辑 今天仿STL functional写了一个bind2nd函数,由于functional里的bind2nd只针对函数对象有效,我在编写时增加了对函数指针也可绑定的情况。但是模板参数类型推导时出现了问题,


//funciotn.h
namespace LouisLib
{
        template<class R , class A1 , class A2 >
struct binary_function
{
typedef R result_type ;
typedef A1 argument1_type ;
typedef A2 argument2_type ;
};

        template<class Pred>
struct binary_traits
{//二元函数对象参数和返回值类型

typedef Pred function_type ;
typedef const Pred & param_type ;
typedef typename Pred::result_type result_type ;
typedef typename Pred::argument1_type argument1_type ;
typedef typename Pred::argument2_type argument2_type ;
};


template<class R , class A1 , class A2>
struct binary_traits< R (*)(A1 , A2) >
{//二元指针函数的返回值以及参数类型
typedef R (*function_type)(A1 , A2 ) ;
typedef R (*param_type)(A1 , A2 ) ;
typedef R result_type ;
typedef A1 argument1_type ;
typedef A2 argument2_type ;
};

        template<class Pred>
struct binder2nd:public unary_function<typename binary_traits<Pred>::result_type ,
typename binary_traits<Pred>::argument1_type>
{
private:
typedef typename binary_traits<Pred>::argument2_type arg2_type ;
arg2_type m_arg ;
typename binary_traits<Pred>::function_type m_op ;

public:
binder2nd( typename binary_traits<Pred>::param_type _pred , arg2_type _val)
:m_op( _pred ) , m_arg( _val ){}

result_type operator ()( argument_type _val )const 
{
return m_op( _val , m_arg ) ;
}

result_type operator()( argument_type _val )
{
return m_op( _val , m_arg ) ;
}
};
        
        template<class Pred , class T >
binder2nd<Pred> bind2nd( const Pred & _pred, const T & _bindVal )//若将此处函数参数改为Pred _pred则可以正常操作


{
typename binary_traits<Pred>::argument2_type val( _bindVal ) ;

return binder2nd<Pred>( (typename binary_traits<Pred>::param_type)(_pred) , val ) ;
}


//测试  test.cpp
int maxVal(int x1 , int x2 )
{
return x1 < x2 ? x2 : x1 ;
}

class maxValClz:public LouisLib::binary_function<int ,int ,int>
{
public:
int operator()(int x1 , int x2 )
{
return x2 < x1 ? x1 : x2 ;
}
};
void FunTest()
{
int x3 = LouisLib::bind2nd<int , int , int>( maxVal , 10 )( 8 ) ;
int x4 = LouisLib::bind2nd( maxValClz() , 10 )( 8 ) ;
}


问题:
当将maxVal作为bind2nd的参数时,binary_traits<Pred>模板推导时仍然会按函数对象形式解析,此时出现类型引用时全出错了。
若将bind2nd模板函数的第一个参数的const修饰 以及 & 引用说明去掉,修改成Pred _pred程序可以正常运行了,但是这样对于函数对象增加了不必要的对象复制开销。请问这是什么原因,有没有好的方法解决这个问题 模板推导,函数对象,函数指针参数
[解决办法]
增加一个针对函数类型的特化就好了。

template<class R , class A1 , class A2>
struct binary_traits< R (A1 , A2) > : binary_traits<R(*)(A1,A2)>
{
};

没有这个的话,m_op 的类型是函数,标准不允许的。
[解决办法]
引用:
谢谢你的回答!
模板显示特化固然可行,但我需要的是调用bind2nd时对普通函数和函数对象在形式上一样的!

那就重载呗。 

#include <stdio.h>

//funciotn.h
namespace LouisLib
{
template<class _Arg,
class _Result>
struct unary_function
{// base class for unary functions
typedef _Arg argument_type;
typedef _Result result_type;
};

template<class R , class A1 , class A2 >
struct binary_function


{
typedef R result_type ;
typedef A1 argument1_type ;
typedef A2 argument2_type ;
};

template<class Pred>
struct binary_traits
{//二元函数对象参数和返回值类型

typedef Pred function_type ;
typedef const Pred & param_type ;
typedef typename Pred::result_type result_type ;
typedef typename Pred::argument1_type argument1_type ;
typedef typename Pred::argument2_type argument2_type ;
};


template<class R , class A1 , class A2>
struct binary_traits< R (*)(A1 , A2) >
{//二元指针函数的返回值以及参数类型
typedef R (*function_type)(A1 , A2 ) ;
typedef R (*param_type)(A1 , A2 ) ;
typedef R result_type ;
typedef A1 argument1_type ;
typedef A2 argument2_type ;
};

template<class Pred>
struct binder2nd: public unary_function<typename binary_traits<Pred>::result_type ,typename binary_traits<Pred>::argument1_type>
{
private:
typedef typename binary_traits<Pred>::argument2_type arg2_type ;
arg2_type m_arg ;
typename binary_traits<Pred>::function_type m_op ;

public:
binder2nd( typename binary_traits<Pred>::param_type _pred , arg2_type _val)
:m_op( _pred ) , m_arg( _val ){}

result_type operator ()( argument_type _val )const 
{
return m_op( _val , m_arg ) ;
}

result_type operator()( argument_type _val )
{
return m_op( _val , m_arg ) ;
}
};

template<class Pred , class T >
binder2nd<Pred> bind2nd( const Pred & _pred, const T & _bindVal )//若将此处函数参数改为Pred _pred则可以正常操作
{
typename binary_traits<Pred>::argument2_type val( _bindVal) ;

return binder2nd<Pred>( (typename binary_traits<Pred>::param_type)(_pred) , val ) ;
}

//重载一下
template<class R , class A1, class A2,  class A3 >
binder2nd<R (*)(A1, A2)> bind2nd(R (*pred)(A1, A2), const A3 & _bindVal )
{
A2 val = _bindVal;
return binder2nd<R (*)(A1, A2)>( (typename binary_traits<R (*)(A1, A2)>::param_type)(pred) , val ) ;


}



//测试  test.cpp
int maxVal(int x1 , int x2 )
{
return x1 < x2 ? x2 : x1 ;
}

class maxValClz : public LouisLib::binary_function<int ,int ,int>
{
public:
int operator()(int x1 , int x2 )
{
return x2 < x1 ? x1 : x2 ;
}
};


}

void FunTest()
{
int x3 = LouisLib::bind2nd(LouisLib::maxVal , 10 )( 11);
int x4 = LouisLib::bind2nd( LouisLib::maxValClz() , 10 )( 8 );
printf("%d,%d\n", x3, x4);
}

int main()
{
FunTest();
return 0;
}

热点排行