簡體   English   中英

通過parent()的qobject_cast的可變參數模板

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM