推导出用于通用引用和指向成员的指针的冲突类型

时间:2018-02-21 14:07:30

标签: c++ c++11 templates forwarding-reference

我想要一个这样的函数:

MyClass

参数是(在文字中,因为C / C ++类型语法是精神上的):

  • 对类的通用引用,例如MyClass
  • 指向T成员函数的const指针,它接受一个unsigned int并返回C

这种工作,但是如果我用l值引用作为第一个参数调用它,我会收到如下错误:

  忽略

候选模板:推导出参数' C'的冲突类型。 (' MyClass&' vs.' MyClass')

据我了解,它是从第一个和第二个参数中推导出typename,但会产生不同的推论并且会混淆。

根据this answer,你可以只对第一个参数进行推论,并以某种方式在第二个参数上使用T关键字。但是,当我希望它推导出参数(C)中的一种类型而不是其他类型(C)时,我无法解决语法问题。

This answer也很有用,但是他们只是根本不使用bash-3.2$ ifconfig en1 en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 24:a0:74:ef:c2:0a inet6 fe80::1421:2877:9b9f:8b7e%en1 prefixlen 64 secured scopeid 0x5 inet 192.168.0.56 netmask 0xffffff00 broadcast 192.168.0.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active bash-3.2$ ping -S 192.168.0.56 www.google.com PING www.google.com (172.217.166.68) from 192.168.0.56: 56 data bytes 64 bytes from 172.217.166.68: icmp_seq=0 ttl=55 time=26.458 ms 64 bytes from 172.217.166.68: icmp_seq=1 ttl=55 time=21.927 ms bASH-3.2$ scapy WARNING: Cannot read wireshark manuf database WARNING: Crypto-related methods disabled for IPsec, Dot11 and TLS layers (needs python-cryptography v1.7+). WARNING: No route found for IPv6 destination :: (no default route?) INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication. WARNING: IPython not available. Using standard Python shell instead. AutoCompletion, History are disabled. aSPY//YASa apyyyyCY//////////YCa | sY//////YSpcs scpCY//Pp | Welcome to Scapy ayp ayyyyyyySCP//Pp syY//C | Version 2.4.0rc4 AYAsAYYYYYYYY///Ps cY//S | pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy SPPPP///a pP///AC//Y | A//A cyP////C | Have fun! p///Ac sC///a | P////YCpc A//A | To craft a packet, you have to be a scccccp///pSP///p p//Y | packet, and learn how to swim in sY/////////y caa S//P | the wires and in the waves. cayCyayP//Ya pY/Ya | -- Jean-Claude Van Damme sY/PsY////YCc aC//Yp | sc sccaCY//PCypaapyCP//YSs spCPY//////YPSps ccaacs >>> sr(IP(dst='www.google.com')/ICMP()) Traceback (most recent call last): File "<console>", line 1, in <module> File "/Library/Python/2.7/site-packages/scapy-2.4.0rc4- py2.7.egg/scapy/sendrecv.py", line 364, in sr s = conf.L3socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) File "/Library/Python/2.7/site-packages/scapy-2.4.0rc4- py2.7.egg/scapy/arch/bpf/supersocket.py", line 57, in __init__ (self.ins, self.dev_bpf) = get_dev_bpf() File "/Library/Python/2.7/site-packages/scapy-2.4.0rc4- py2.7.egg/scapy/arch/bpf/core.py", line 98, in get_dev_bpf raise Scapy_Exception("No /dev/bpf handle is available !") Scapy_Exception: No /dev/bpf handle is available 的引用来解决它,在这种情况下同样有效,但不在我的。< / p>

这可能吗?

2 个答案:

答案 0 :(得分:7)

对于第一个参数,左值C将被推断为左值引用类型(即您的案例的MyClass &),这是forwarding reference的预期行为;您可以在第二个参数中使用C时通过std::remove_reference删除引用,例如

template<typename C, typename T>
void foo(C &&aclass, T (std::remove_reference_t<C>::*const memberFunc)(unsigned)) {

}

正如@Quentin所指出的那样,使用std::remove_reference也会引入non-deduced context,这会阻止从第二个参数推断C

答案 1 :(得分:0)

实际上我发现有一个通用引用重载将它转发到l值引用版本。虽然不是特别优雅;我觉得应该有更好的方法。

template<typename C, typename T>
void foo(C &aclass, T (C::*const memberFunc)(unsigned)) {
  // Code goes here.
}

template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {
  foo(aclass, memberFunc);
}