C++ qobject_通过父对象()强制转换的可变模板
大师和模板专家们,我需要你们的帮助 我目前正在寻找检查QObject父层次结构的解决方案。我有一个具有以下层次结构(父到子)的自定义QDialog: 在CustomDialog类中,我想检查对话框的层次结构是否与此示例匹配,因此我检查了这是否可以通过可变模板实现,例如: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
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获取最后一个参数的解决方案