[英]Variadic Template for qobject_cast via parent()
專家和模板專家,我需要您的幫助...
我目前正在尋找有關檢查QObject父級層次結構的解決方案。 我有一個具有以下層次結構的父級QDialog(父級到子級):
QDockWidget
> CustomDockArea
> QMainWindow
> QDockWidget
> CustomDialog
在CustomDialog類中,我想檢查對話框的層次結構是否與此示例匹配,因此我檢查了它是否可以通過可變參數模板完成,例如:
assert(qobject_cast_parent<QDockWidget*, QMainWindow*, CustomDockArea*, QDockWidget*>(this));
我想出了這樣的東西:
template <class T, class... Ts>
inline T qobject_cast_parent(QObject* root)
{
if (root)
{
if (sizeof...(Ts) == 0)
{
return qobject_cast<T>(root->parent());
}
else
{
return qobject_cast_parent<Ts...>(root->parent());
}
}
else
{
return nullptr;
}
}
但是,有一些問題:在我們的示例QDockWidget *中,我需要參數包的最后一個參數作為函數的返回類型。 我可以將第一個參數作為返回類型,但這會使模板調用有點麻煩。 但是,即使可以解決,我認為參數包“展開”的方式仍然存在問題,現在我有點不確定我的模板方法對於原始問題是否可行。 也許您可以給我一些提示。 提前致謝!!!
使用c ++ 14,您可以簡單地使用auto
作為返回類型:
template <class T>
T* qobject_cast_parent(QObject* root)
{
return root
? qobject_cast<T*>(root->parent())
: nullptr;
}
template <class T, class T2, class... Ts>
auto qobject_cast_parent(QObject* root)
//-> typename Last<T2, Ts...>::type /* In c++11, you have to create this traits */
{
return root
? qobject_cast_parent<T2, Ts...>(qobject_cast<T*>(root->parent()))
: nullptr;
}
由於我沒有完整的代碼,因此我只能確認以下編譯器無法進行測試。 我相信您可以為我測試一下,如果這不起作用或者我誤解了您的問題,請告訴我。
#include <QtCore/QObject>
#include <cassert>
#include <type_traits>
// This ends the recursion with the actual qobject_cast.
template <class T, class U>
inline U *qobject_cast_parent(T* root)
{
// Make sure everything's a QObject, clear message if not.
static_assert(std::is_base_of<QObject, T>::value, "Object must be a QObject");
if (root)
{
return qobject_cast<U *>(root->parent());
}
else
{
return nullptr;
}
}
template <class T, class U, class... Us>
inline U *qobject_cast_parent(T* root)
{
// Make sure everything's a QObject, clear message if not.
static_assert(std::is_base_of<QObject, T>::value, "Object must be a QObject");
if (root)
{
return qobject_cast_parent<U, Us...>(qobject_cast<U *>(root->parent()))
}
else
{
return nullptr;
}
}
因此,模板參數是從子級到父級排序的,並且您還將被迫指定最里面的類型。 因此,我認為您的assert
示例將如下所示(再次未經測試,請讓我知道它的工作原理):
assert(qobject_cast_parent<CustomDialog,
QDockWidget,
QMainWindow,
CustomDockArea,
QDockWidget>(this));
編輯 :為了完整起見,您還詢問一種獲取參數包最后一個參數類型的方法。 您可以使用如下形式:
template <typename T, typename... Ts>
struct Last
{
typedef typename Last<Ts...>::type type;
};
template <typename T>
struct Last<T>
{
typedef T type;
};
int main()
{
// For example, this gives std::string:
Last<int, float, char, std::string>::type foo = "bar";
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.