函数的部分模板专用化,该函子调用传递给它的对象的成员方法

Partial template specialisation of a functor that's calling a member method of objects passed to it

本文关键字:调用 成员方法 对象 专用 函数      更新时间:2023-10-16

我有以下函子及其部分专门化

template    <class _T, typename _Return = void, typename _Arg = void>
struct  Caller
{
    typedef _Return(_T::*Method)(_Arg);
    Caller(Method pm, _Arg a)
    :   _pMethod(pm),
        _arg(a)
    {}
    _Return operator()(_T& obj)
    {
        return (obj.*_pMethod)(_arg);
    }
    Method  _pMethod;
    _Arg    _arg;
};
template    <class _T, typename _Return>
struct  Caller<_T, _Return, void>
{
    typedef _Return(_T::*Method)();
    Caller(Method pm)
    :   _pMethod(pm)
    {}
    _Return operator()(_T& obj)
    {
        return (obj.*_pMethod)();
    }
    Method  _pMethod;
};

我正试着这样使用它:

struct Foo
{
    void Bar() const
    {
         void(0);
    }
};
// ...
std::list<Foo> foos;
const std::list<Foo> &rFoos(foos);
std::for_each(rFoos.begin(), rFoos.end(), Caller<const Foo>(&Foo::Bar));

我得到这个,对于最后一行代码(IDE在调用者处拾取):

错误C2440: ":无法从'void '转换(__thiscall Foo:: *)(空白)常量"Caller<_T>"1> 与1> [1> _T=const Foo1> ]1>没有构造函数可以接受源类型,或者构造函数重载分辨率不明确

这段代码可以在g++环境中工作。(如果我 CC_g++会抱怨,这是有道理的,因为函数只会在const对象上调用)。

我尝试了各种方法,包括在函子中添加operator()(const _T& obj)/operator()(const _T& obj) const品种,但无济于事。

这将被编译器接受:

struct Foo
{
    void Bar()
    {
         void(0);
    }
};
// ...
std::list<Foo> foos;
const std::list<Foo> &rFoos(foos);
std::for_each(rFoos.begin(), rFoos.end(), Caller<Foo>(&Foo::Bar));

我做错了什么?如何使函数模板在Visual c++中为const成员函数工作?

我认为Caller_T的稳定性并没有反映在this中MSVC中Method的自动一致性(如果有的话,我觉得GCC的行为你提到是奇怪的)。
如果想在this的一致性中反映_T的一致性,像下面这样准备辅助类Caller<Foo>(&Foo::Bar)0怎么样根据T_的一致性选择合适的签名

template <class C, class T, class Const_T>
struct Select_Type { typedef T type; };
template <class C, class T, class Const_T>
struct Select_Type<C const, T, Const_T> { typedef Const_T type; };
template    <class _T, typename _Return>
struct  Caller<_T, _Return, void>
{
    typedef typename Select_Type<
        _T, _Return(_T::*)(), _Return(_T::*)()const >::type Method;
    ....

您的operator()函数需要是const(它们不改变函子本身,但我不认为您需要一组新的函数)。

还要注意,所有以下划线和大写字母开头的类型都是为实现标准保留的。