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

时间:2015-08-01 21:29:11

标签: 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
    }
};

我希望::foobar的调用能够明确地解析为标有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;
          ^

为什么我不清楚我想拨打哪个版本?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

问题是当从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){}));

答案 1 :(得分:0)

您可以使构造函数采用std::string参数explicit。这样编译器就无法进行从std::stringFoo的隐式转换。