cast via parent()
gurus and template-experts, I need your help ...
I am currently looking for a solution on checking a QObject's parent hierarchy. I have a custom QDialog with the following hierarchy (parent to child):
QDockWidget
> CustomDockArea
> QMainWindow
> QDockWidget
> CustomDialog
Within the CustomDialog class, I want to check if the dialog's hierarchy matches this example, so I checked if this is accomplishable with a variadic template, for example:
assert(qobject_cast_parent<QDockWidget*, QMainWindow*, CustomDockArea*, QDockWidget*>(this));
and I have come up with something like 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;
}
}
However, there a few problems: I need the last parameter of the parameter pack as being the return type of the function, in our example QDockWidget*. I could take the first parameter as being the return type, but this would make the template call a little bit cumbersome. However, even if that would be solved, I think there is still a problem with the way the parameter pack is "unrolled" and now I got a little bit unsure if my template-approach is even feasible for the original problem. Maybe you can give me some hints. Thanks in advance!!!
使用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;
}
As I don't have your complete code, I can only confirm that the following compiles, but could not test it. I'm sure you can test it for me though, let me know if this doesn't work or if I misunderstood your problem.
#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;
}
}
So the template parameters are ordered from child to parent, and you'll be forced to specify the innermost type as well. So I think your assert
example would look like this (again, untested, let me know how it works out):
assert(qobject_cast_parent<CustomDialog,
QDockWidget,
QMainWindow,
CustomDockArea,
QDockWidget>(this));
Edit : For sake of completeness, you were also asking about a way to get to the type of last parameter of a parameter pack. You could use something like 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;
}
链接地址: http://www.djcxy.com/p/66894.html
上一篇: 变量模板类中定义的数量有所不同
下一篇: 通过父母投射()