C++11 std::function const 重载歧义

标签 c++11 overloading std-function const-correctness

我在一个较大程序的一部分上遇到了问题,其中我所说的明确的内容被 g++ 认为是不明确的。和clang++

#include <functional>
#include <string>

struct Foo {
    Foo(int) {}
    Foo(std::string) {}
    operator int () const { return 42; }
    operator std::string () const { return ""; }

    void foo(std::function<void(Foo&, int)>f);
    void foo(std::function<void(const Foo&, int)>f) const; // xxx

    void foo(std::function<void(const std::string&, Foo&)>f);
    void foo(std::function<void(const std::string&, const Foo&)>f) const;

    void bar() const {
        this->foo([](const Foo&, int){}); // xxx
    }
};

我期望调用 ::foo制造于bar明确解析为标有 xxx 的 const 版本,而两个编译器都提示重载解析不明确:

g++ -std=c++11 -c -Wall amb.cpp 
amb.cpp: In member function ‘void Foo::bar() const’:
amb.cpp:18:40: error: call of overloaded ‘foo(Foo::bar() const::<lambda(const Foo&, int)>)’ is ambiguous
         this->foo([](const Foo&, int){});
                                        ^
amb.cpp:12:10: note: candidate: void Foo::foo(std::function<void(const Foo&, int)>) const
     void foo(std::function<void(const Foo&, int)>f) const;
          ^
amb.cpp:15:10: note: candidate: void Foo::foo(std::function<void(const std::basic_string<char>&, const Foo&)>) const
     void foo(std::function<void(const std::string&, const Foo&)>f) const;
          ^

为什么不清楚我要调用哪个版本?我该如何解决这个问题?

最佳答案

问题在于,从 lambda 传递到 std::function 时,某些类型信息会丢失。对象(特别是参数类型)。

更具体地说,例如接受 std::function<void(int)> 的函数另一个接受 std::function<void(double)> void 被认为是同样好的重载lambda 接受 int论证。

例如

#include <functional>

void foo(std::function<void(int)>f);
void foo(std::function<void(double)>f);

void bar() {
    foo([](int){});
}

调用bar被认为是不明确的

amb2.cpp: In function ‘void bar()’:
amb2.cpp:8:18: error: call of overloaded ‘foo(bar()::<lambda(int)>)’ is ambiguous
     foo([](int){});
                  ^
amb2.cpp:4:6: note: candidate: void foo(std::function<void(int)>)
 void foo(std::function<void(int)>f);
      ^
amb2.cpp:5:6: note: candidate: void foo(std::function<void(double)>)
 void foo(std::function<void(double)>f);
      ^

解决方法

解决方案是显式创建正确的 std::function对象:

this->foo(std::function<void(const Foo&, int)>([](const Foo&, int){}));

关于C++11 std::function const 重载歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31766405/

相关文章:

c++ - 使用 Xcode 4.5 调试 c++ 时,单步执行代码会停止在 STL 代码上

c++ - C++ 中的函数重载与默认参数

c++ - 什么时候捕获捕获变量?

c++ - 以 std::array of doubles 作为参数或将 double 单独作为参数转换函数

c++ - 迭代 vector 时自动与具体类型?

c++ - std::istream_iterator<double> 成员变量在递增时失败

c++ - C++ 标准对使用 noexcept 覆盖 throw() 函数有何规定?

c++ - 无法解决错误 : non-const lvalue reference to type 'bool' cannot bind to a temporary of type 'bool'

c# - 重载 "base"构造函数或 "this"构造函数?

c++ - 使用 std::function 进行模板类型推导