如何使用std :: shared_ptr <void>和另一种类型的std :: shared_ptr进行函数重载?

alm*_*now 13 c++ overloading std shared-ptr c++11

试试以下代码:

#include <functional>
#include <memory>

class C {
    public:
    void F(std::function<void(std::shared_ptr<void>)>){}
    void F(std::function<void(std::shared_ptr<int>)>){}
};

int main(){
    C c;
    c.F([](std::shared_ptr<void>) {});
}
Run Code Online (Sandbox Code Playgroud)

您将看到编译错误:

prog.cc:12:7: error: call to member function 'F' is ambiguous
    c.F([](std::shared_ptr<void>) {});
    ~~^
prog.cc:6:10: note: candidate function
    void F(std::function<void(std::shared_ptr<void>)>){}
         ^
prog.cc:7:10: note: candidate function
    void F(std::function<void(std::shared_ptr<int>)>){}
         ^
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这种模棱两可的问题?也许与SFINAE?

max*_*x66 6

我很困惑,但我试着解释一下.

我看你的拉姆达可以通过双方所接受 std::function<void(std::shared_ptr<void>)>std::function<void(std::shared_ptr<int>)>; 您可以验证以下两行是否都可以编译

std::function<void(std::shared_ptr<void>)>  f0 = [](std::shared_ptr<void>){};
std::function<void(std::shared_ptr<int>)>   f1 = [](std::shared_ptr<void>){};
Run Code Online (Sandbox Code Playgroud)

这是因为(我想)一个共享指针int可以转换为共享指针void; 你可以验证以下行编译

std::shared_ptr<void> sv = std::shared_ptr<int>{};
Run Code Online (Sandbox Code Playgroud)

此时我们可以看到调用

c.F([](std::shared_ptr<void>) {});
Run Code Online (Sandbox Code Playgroud)

你没有传递std::function<void(std::shared_ptr<void>)>F(); 你传递可以转换到两个对象std::function<void(std::shared_ptr<void>)>std::function<void(std::shared_ptr<int>)>; 所以可以用来调用两个版本的对象F().

所以模棱两可.

有没有办法解决这种模棱两可的问题?也许与SFINAE?

也许用标签调度.

您可以添加未使用的参数和模板 F()

void F (std::function<void(std::shared_ptr<void>)>, int)
 { std::cout << "void version" << std::endl; }

void F (std::function<void(std::shared_ptr<int>)>, long)
 { std::cout << "int version" << std::endl; }

template <typename T>
void F (T && t)
 { F(std::forward<T>(t), 0); }
Run Code Online (Sandbox Code Playgroud)

这样打电话

c.F([](std::shared_ptr<void>) {});
c.F([](std::shared_ptr<int>){});
Run Code Online (Sandbox Code Playgroud)

你从第一次调用中获得"void version"(非模板F()匹配,但是"void version"是首选,因为0是a int)和第二次调用的F()"int version" (只有"int version"匹配).