试用以下代码:
#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>) {});
}
您会看到一个编译错误:
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>)>){}
^
有什么办法可以解决这种歧义?也许与SFINAE合作?
我很困惑,但我尝试解释一下。
我看你的拉姆达可以通过双方所接受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>){};
这是因为(我想)共享指针int
可以转换为共享指针void
。您可以验证以下行是否已编译
std::shared_ptr<void> sv = std::shared_ptr<int>{};
至此,我们可以看到
c.F([](std::shared_ptr<void>) {});
你不会传递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); }
这样打电话
c.F([](std::shared_ptr<void>) {});
c.F([](std::shared_ptr<int>){});
您可以从第一个调用中获得“无效版本”(两个非模板都F()
匹配,但首选“无效版本”,因为0
它是int
),而从第二个调用中获得F()
“ int版本” (仅匹配“ int版本”)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句