我编写了一个模板函数,该函数可以传递给QTcpServer或QBluetoothServer。它获取下一个挂起的连接,并绑定它的几个事件处理程序。(真正的函数也包含一些错误处理和其他内容,但它们与问题无关,所以我省略了它们(。
template <typename T> static void clientConnected(T * server) {
auto clientsocket = server->nextPendingConnection();
clientsocket将是QTcpSocket或QBluetoothSocket,具体取决于服务器的类型。
我可以使用公共基类QIODevicece绑定readyRead信号。
QObject::connect(clientsocket,&QIODevice::readyRead, [=](){readyRead(clientsocket);});
然而,对于断开的信号不存在这样的公共基类。因此,我需要知道clientsocket是指向什么类型的指针,以便选择要绑定的正确信号。我想出了。
QObject::connect(clientsocket,&std::remove_reference<decltype(*clientsocket)>::type::disconnected, [=](){readyRead(clientsocket);});
哪种方法有效,但似乎并不令人惊讶,有没有更简洁的方法来获取指针的目标类型?
根据要求,下面有一个最小的可编译示例,其中可以测试任何替代溶液。
#include <QTcpServer>
#include <QBluetoothServer>
#include <QTcpSocket>
#include <QBluetoothSocket>
template <typename T> static void clientConnected(T * server) {
auto clientsocket = server->nextPendingConnection();
QObject::connect(clientsocket,&std::remove_reference<decltype(*clientsocket)
}
void baz() {
QTcpServer * foo = new QTcpServer();
clientConnected(foo);
QBluetoothServer * bar = new QBluetoothServer(QBluetoothServiceInfo::RfcommP
clientConnected(bar);
}
使用编译
gcc -fPIC `pkg-config --cflags Qt5Bluetooth` `pkg-config --cflags Qt5Network` -c targettype.cpp
将左值(例如延迟clientsocket
变量(传递给decltype()
会返回一个引用类型,因此如果要使用decltype
,则需要使用std::remove_reference
或std::remove_pointer
来访问被引用的类型,这是无法绕过的。
在C++14及更高版本中,您可以使用std::remove_reference_t<T>
而不是std::remove_reference<T>::type
(或使用std::remove_pointer_t<T>
而不是std::remove_pointer<T>::type
(,这将保存几个字符:
QObject::connect(
clientsocket,
&std::remove_reference_t<decltype(*clientsocket)>::disconnected,
[=](){ disconnected(clientsocket); }
);
QObject::connect(
clientsocket,
&std::remove_pointer_t<decltype(clientsocket)>::disconnected,
[=](){ disconnected(clientsocket); }
);
如果你真的想要更短的,你可以使用using
别名:
template<typename T>
using no_ref = typename std::remove_reference<T>::type;
// = std::remove_reference_t<T>;
QObject::connect(
clientsocket,
&no_ref<decltype(*clientsocket)>::disconnected,
[=](){ disconnected(clientsocket); }
);
template<typename T>
using no_ptr = typename std::remove_pointer<T>::type;
// = std::remove_pointer_t<T>;
QObject::connect(
clientsocket,
&no_ptr<decltype(clientsocket)>::disconnected,
[=](){ disconnected(clientsocket); }
);
在C++17及更高版本中,可以使用if constexpr
来区分这两种类型,例如:
auto handler = [=](){ disconnected(clientsocket); };
if constexpr (std::is_same_v<decltype(*clientsocket), QBluetoothSocket&>)
QObject::connect(clientsocket, &QBluetoothSocket::disconnected, handler);
else
QObject::connect(clientsocket, &QTcpSocket::disconnected, handler);
然而,有一个更简单的解决方案根本不需要使用decltype
:
template<typename T>
using signalType = void(T::*)();
template<typename T>
signalType<T> getDisconnectedSignal(T*)
{
return &T::disconnected;
}
QObject::connect(
clientsocket,
getDisconnectedSignal(clientsocket),
[=](){ disconnected(clientsocket); }
);
只需使用std::remove_pointer
(或C++14中的std::remove_pointer_t
(。
using t = typename std::remove_pointer<int*>::type; // t = int.