Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ qobject_通过父对象()强制转换的可变模板_C++_Qt_Templates_C++11_Variadic Templates - Fatal编程技术网

C++ qobject_通过父对象()强制转换的可变模板

C++ qobject_通过父对象()强制转换的可变模板,c++,qt,templates,c++11,variadic-templates,C++,Qt,Templates,C++11,Variadic Templates,大师和模板专家们,我需要你们的帮助 我目前正在寻找检查QObject父层次结构的解决方案。我有一个具有以下层次结构(父到子)的自定义QDialog: 在CustomDialog类中,我想检查对话框的层次结构是否与此示例匹配,因此我检查了这是否可以通过可变模板实现,例如: assert(qobject_cast_parent<QDockWidget*, QMainWindow*, CustomDockArea*, QDockWidget*>(this)); assert(qobjec

大师和模板专家们,我需要你们的帮助

我目前正在寻找检查QObject父层次结构的解决方案。我有一个具有以下层次结构(父到子)的自定义QDialog:

在CustomDialog类中,我想检查对话框的层次结构是否与此示例匹配,因此我检查了这是否可以通过可变模板实现,例如:

assert(qobject_cast_parent<QDockWidget*, QMainWindow*, CustomDockArea*, QDockWidget*>(this));
assert(qobject\u cast\u parent(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;
    }
}
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;
}
模板
内联T qobject\u cast\u父对象(qobject*根)
{
如果(根)
{
如果(sizeof…(Ts)==0)
{
返回qobject_cast(root->parent());
}
其他的
{
返回qobject\u cast\u parent(根->父());
}
}
其他的
{
返回空ptr;
}
}

但是,有几个问题:在我们的示例QDockWidget*中,我需要参数包的最后一个参数作为函数的返回类型。我可以将第一个参数作为返回类型,但这会使模板调用有点麻烦。然而,即使可以解决这个问题,我认为参数包“展开”的方式仍然存在问题,现在我有点不确定我的模板方法对于最初的问题是否可行。也许你能给我一些提示。提前感谢

由于我没有您的完整代码,我只能确认以下代码已编译,但无法对其进行测试。我相信你可以为我测试一下,如果这不起作用或者我误解了你的问题,请告诉我

#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;
  }
}
编辑:为了完整起见,您还询问了获取参数包最后一个参数类型的方法。您可以使用以下内容:

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;
    }
}
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;
}
模板
最后构造
{
typedef typename Last::type type;
};
模板
最后构造
{
T型;
};
int main()
{
//例如,这将给出std::string:
Last::type foo=“bar”;
返回0;
}

由于我没有您的完整代码,我只能确认以下代码已编译,但无法对其进行测试。我相信你可以为我测试一下,如果这不起作用或者我误解了你的问题,请告诉我

#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;
  }
}
编辑:为了完整起见,您还询问了获取参数包最后一个参数类型的方法。您可以使用以下内容:

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;
    }
}
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;
}
模板
最后构造
{
typedef typename Last::type type;
};
模板
最后构造
{
T型;
};
int main()
{
//例如,这将给出std::string:
Last::type foo=“bar”;
返回0;
}

使用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;
}
模板
T*qobject\u cast\u父对象(qobject*root)
{
返回根
?qobject_cast(根->父对象())
:nullptr;
}
模板
自动qobject\u cast\u父对象(qobject*根)
//->typename Last::type/*在c++11中,您必须创建以下特性*/
{
返回根
?qobject\u cast\u父对象(qobject\u cast(根->父对象())
:nullptr;
}

使用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;
}
模板
T*qobject\u cast\u父对象(qobject*root)
{
返回根
?qobject_cast(根->父对象())
:nullptr;
}
模板
自动qobject\u cast\u父对象(qobject*根)
//->typename Last::type/*在c++11中,您必须创建以下特性*/
{
返回根
?qobject\u cast\u父对象(qobject\u cast(根->父对象())
:nullptr;
}

“我想检查层次结构是否正确。”为什么
CustomDialog
关心整个层次结构树?这是一个对话框,它应该可以在没有父对象的情况下单独使用。。。当然,如果它有正确的父节点指向树的根,那么它可以增加它的功能,但是您不应该关心这些父节点的确切位置。你可以简单地使用第一个和第二个
QDockWidget
来提升层次结构,但即便如此,我认为这样的界面还是很笨重。也许你应该公开几个信号/插槽,并提供一个助手方法将它们连接到某棵树上。单词“correct”可能有误导性,我相应地编辑了我的答案。对话框的行为取决于它在层次结构中的位置,因此需要进行某些检查。也许应该从了解层次结构的代码中明确告诉对话框该做什么?那会干净得多。实际上,您正在向对话框公开一个API,而该API并没有用类的签名表示……”“我想检查层次结构是否正确。”为什么
CustomDialog
关心整个层次结构树?这是一个对话框,它应该可以在没有父对象的情况下单独使用。。。当然,如果它有正确的父节点指向树的根,那么它可以增加它的功能,但是您不应该关心这些父节点的确切位置。你可以简单地使用第一个和第二个
QDockWidget
来提升层次结构,但即便如此,我认为这样的界面还是很笨重。也许你应该公开几个信号/插槽,并提供一个助手方法将它们连接到某棵树上。单词“correct”可能有误导性,我相应地编辑了我的答案。对话框的行为取决于它在层次结构中的位置,因此需要进行某些检查。也许应该从了解层次结构的代码中明确告诉对话框该做什么?那会干净得多。事实上,您正在向您的对话框公开一个API,而该API并不是用类的签名来表示的……谢谢您的时间!它还没有完全工作,我得到“无法使用[U=QMainWindow T=QDockWidget]将参数1从'CustomDialog*'转换为'QDockWidget*”。。。然而,这个结束递归的模板对我的解决方案很有帮助,所以我认为我实际上非常接近,我还有一个从参数包和returnin获取最后一个参数的解决方案