关于函数指针与类作模板参数的类型推导问题
本帖最后由 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 ) ;
}
template<class R , class A1 , class A2>
struct binary_traits< R (A1 , A2) > : binary_traits<R(*)(A1,A2)>
{
};
#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;
}