如何在宏中获取智能指针的类型?

How to get type of smart pointer in macros?

这行太长了:

btnNickname = TWeakObjectPtr<UButton>(Cast<UButton>(WidgetTree->FindWidget(FName(STRINGIFY(btnNickname))));

对于定义为的变量:

TWeakObjectPtr<UButton> btnNickname;

我想创建宏来减少代码:

FIND_WIDGET(btnNickname);

有什么办法吗?

我现在使用这个代码:

#define FIND_WIDGET(TYPE, NAME) NAME = TWeakObjectPtr<TYPE>(Cast<TYPE>(WidgetTree->FindWidget(FName(STRINGIFY(NAME)))))

但是宏有两个参数。我可以从 TWeakObjectPtr 变量中获取指针类型吗? decltype 可以给我变量类型,但不能给我指针数据类型。

物质:

#define FIND_WIDGET(NAME) NAME = TWeakObjectPtr<decltype(*NAME)>(Cast<decltype(*NAME)>(WidgetTree->FindWidget(FName(STRINGIFY(NAME)))))

但这行不通。

P.S。 TWeakObjectPtr是Unreal Engine中使用的智能指针 4.

大概是这样的:

template <typename T>
TWeakObjectPtr<T> FindWidgetHelper(
    TWidgetTree* tree, const char* name, TWeakObjectPtr<T> widget) {
  return TWeakObjectPtr<T>(Cast<T>(tree->FindWidget(FName(name))));
}

#define FIND_WIDGET(NAME) \
NAME = FindWidgetHelper(WidgetTree, STRINGIFY(NAME), NAME)

根据口味调整。我对Unreal Engine完全不熟悉,不得不猜测各种事物的类型。

从智能指针中提取类型的一种简单方法可能是(未经测试):

template<typename T> struct Untweaker;
template<typename T> struct Untweaker<TWeakObjectPtr<T>> {
  using type = T;
}
template<typename T> using Untweak = typename Untweaker<T>::type;

然后你可以使用Untweak<decltype(variable)>来提取实际类型。

您可以 TWeakObjectPtr::GetEvenIfUnreachable 找到给定 TWeakObjectPtr 的类型,如下所示:

remove_pointer_t<decltype(btnNickname.GetEvenIfUnreachable())>

[Simplified Example]

所以基本上只需将其插入您现有的宏即可:

#define FIND_WIDGET(NAME) NAME = TWeakObjectPtr<remove_pointer_t<decltype(NAME.GetEvenIfUnreachable())>>(Cast<remover_pointer_t<decltype(NAME.GetEvenIfUnreachable())>>(WidgetTree->FindWidget(FName(STRINGIFY(NAME)))))

完全公开我不得不询问如何获得这些类型:

我认为它不起作用的原因是 decltype(*NAME) 是引用类型,因此您需要删除引用:

std::remove_reference_t<decltype(*NAME)>

或者您可以这样做:

std::remove_pointer_t<decltype(NAME.operator->())>

但无论如何您都不应该使用宏。宏的气味和 parents 会指着你并告诉他们 children 不要靠近使用宏的坏人。编写 C++,而不是宏。

编译器可以很容易地推导出object的类型:

template<typename T>
  inline void
  find_widget(TWeakObjectPtr<T>& t, const char* name)
  {
    t = TWeakObjectPtr<T>(Cast<T>(WidgetTree->FindWidget(FName(name))));
  }

然后:

find_widget(foo, STRINGIFY(foo));

这更灵活,因为您还可以:

find_widget(foo, "something else");

N.B。 find_widget 对于修改参数的东西来说似乎不是一个很好的名字。