【问题标题】:How to get type of smart pointer in macros?如何在宏中获取智能指针的类型?
【发布时间】:2015-10-02 13:55:24
【问题描述】:

这行太长了:

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)))))

但这不起作用。

附: TWeakObjectPtr 是虚幻引擎 4 中使用的智能指针。

【问题讨论】:

  • 空白(包括新行)是免费的!使用它们而不是宏
  • 我对虚幻智能指针不熟悉,但智能指针通常具有它们所管理的对象的类型定义在其中。所以你应该可以从指针的类型中得到它。
  • 我有一个关于从模板化对象中提取类型的类似问题:stackoverflow.com/q/31429363/2642059 那里接受的答案指出 C++ 标准类提供了typedefs,它们被定义为模板参数,因此它们可以以后可以参考。也许TWeakObjectPtr 有类似的typedef
  • 宏很烂。直接说不吧。
  • @JonathanWakely 我几乎普遍同意你的观点,但我不得不说,出于调试目的,STRINGIFY 非常有帮助。

标签: c++ pointers macros smart-pointers decltype


【解决方案1】:

我认为它不起作用的原因是 decltype(*NAME) 是一个引用类型,所以你需要剥离引用:

std::remove_reference_t<decltype(*NAME)>

或者你可以这样做:

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

但无论如何你都不应该使用宏。有宏的气味,父母会指着你告诉他们的孩子不要靠近使用宏的坏人。编写 C++,而不是宏。

编译器可以很容易地推断出对象的类型:

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");

注意find_widget 对于修改其论点的东西来说似乎不是一个很好的名字。

【讨论】:

  • 感谢您的详细回复!很有帮助的信息。我不会使用宏并使用此模板。那么这个函数的更好的名字呢? :)
【解决方案2】:

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

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&lt;decltype(variable)&gt;来提取实际类型。

【讨论】:

    【解决方案3】:

    大概是这样的:

    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)
    

    根据口味调整。我对虚幻引擎一点也不熟悉,不得不对各种事物的类型进行一些猜测。

    【讨论】:

      【解决方案4】:

      您可以通过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)))))
      

      完全披露我不得不询问如何获得这些类型:Getting the Return Type of a Templatized Object's Method

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-31
        • 1970-01-01
        • 2011-08-02
        相关资源
        最近更新 更多