3

我有以下函子及其部分特化

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::* )(void) const' 转换为 'Caller<_T>' 1> with 1> [ 1> _T=const Foo 1> ] 1> 没有构造函数可以取源类型,或构造函数重载决议不明确

此代码将在 g++ 环境中工作。(如果我Caller<Foo>(&Foo::Bar)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 成员函数?

4

2 回答 2

1

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

另请注意,所有以下划线和大写字母开头的类型都被标准保留用于实现。

于 2011-07-15T15:23:46.270 回答
1

我认为 in 的 constness_TCaller没有反映在MSVCthisMethod自动 的 constness (如果有的话,我觉得你提到的 GCC 的行为很奇怪)。
如果要在 的 的 constness 中体现 的 constness _Tthis如何准备Select_Type如下辅助类,并根据 的 constness 选择合适的签名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;
    ....
于 2011-07-15T16:04:07.167 回答