Const调用操作符调用绑定的非Const成员函数

const call operator calling bound non-const member function

本文关键字:Const 成员 函数 绑定 调用操作符 调用      更新时间:2023-10-16

以下代码在我尝试过的每个编译器(gcc 4.9.2, clang 3.6和VS 2015)上编译良好。然而VS 2013更新4的错误,我将在下面详细说明。这是编译器中的错误吗?

#include <iostream>
#include <functional>
template<typename Func>
struct Bar
{
    Func f_;
    Bar(Func f) : f_(f) { }
    void operator()() const
    {
        f_();
    }
};
template<typename T>
void Baz(T const& t)
{
    Bar<T> b(t);
    b();
}
struct Foo 
{ 
    Foo()
    {
        auto r = std::bind(&Foo::DoFoo, this);
        Baz(r);
    }
    void DoFoo() { std::cout << "Doing Foo!n"; } 
};
int main()
{
    Foo f;
    return 0;
}

错误列表如下:

1>doodle.cpp(15): error C3848: expression having type 'const std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >' would lose some const-volatile qualifiers in order to call 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >::operator ()<>(void)'
1>          doodle.cpp(14) : while compiling class template member function 'void Bar<T>::operator ()(void) const'
1>          with
1>          [
1>              T=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >
1>          ]
1>          doodle.cpp(23) : see reference to function template    instantiation 'void Bar<T>::operator ()(void) const' being compiled
1>          with
1>          [
1>              T=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >
1>          ]
1>          doodle.cpp(22) : see reference to class template instantiation 'Bar<T>' being compiled
1>          with
1>          [
1>              T=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >
1>          ]
1>          doodle.cpp(31) : see reference to function template instantiation 'void Baz<std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >>(const T &)' being compiled
1>          with
1>          [
1>              T=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Foo::* )(void),void,Foo,>,Foo *const >
1>          ]

我认为它想要DoFoo()是一个const成员函数,但修复它没有帮助。

这似乎是一个VS2013编译器的错误,有两种方法来解决它:

使用std::function代替auto来存储对成员函数的调用

std::function<void()> r = std::bind(&Foo::DoFoo, this);

或从Bar

中的函数调用operator()中删除const
template<typename Func>
struct Bar
{
    Func f_;
    Bar(Func f) : f_(f) { }
    void operator()() // const
    {
        f_();
    }
};