为啥不使用#define 来隐藏unique_ptr ugliness 在这里工作?

Posted

技术标签:

【中文标题】为啥不使用#define 来隐藏unique_ptr ugliness 在这里工作?【英文标题】:Why isn't using #define to hide unique_ptr ugliness working here?为什么不使用#define 来隐藏unique_ptr ugliness 在这里工作? 【发布时间】:2013-02-07 00:27:54 【问题描述】:

以下隐藏 unique_ptr 丑陋的“技巧”有什么问题?

class Drawable;
typedef unique_ptr<Drawable> pDrawable;
#define newDrawable(...) pDrawable(new Drawable (##__VA_ARGS__))

前两个很好。但是第三个在VS2012中导致错误:

 23 IntelliSense: "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx>::
_Myt &) [with _Ty=Drawable, _Dx=std::default_delete<Drawable>]" (declared at line 1447 of
"C:\vs2012\VC\include\memory") is inaccessible  file.h  36  26  

我不明白为什么这不起作用,除非我误解了 C++ 定义宏的工作原理。我认为它会简单地替换此代码:

newDrawable(a, b, c)

unique_ptr<Drawable>(new Drawable(a, b, c));

我知道 unique_ptr 不能被复制,但我不是在复制它,在这里。我是吗?

编辑:

我收到了一些“使用”相关宏的请求:

如果我使用它,它的用法如下:

pDrawable myDraw = newDrawable();

我想翻译成:

unique_ptr<Drawable> myDraw = unique_ptr<Drawable>(new Drawable());

但是,如果没有 Visual Studio 给出以下错误,我什至无法编译宏。就好像#define 中的某些内容本身是不允许的。错误在我进行定义的那一行返回,而不是在我调用定义的那一行。

请参阅此处了解为什么 make_unique 不起作用:make_unique does not compile

edit2

我已经回答了下面的问题。上面的代码确实可以编译,并且可以工作。

【问题讨论】:

你如何在完整的语句中实际使用newDrawable() 你不写自己的make_unique?因为真诚地,这个宏方式更丑:/ 我怀疑您使用它来代替make_unique,因为这是与make_shared 类似的用例。 Herb Sutter 有一个 make_unique here 的实现示例。 如果他们记得将它包含在标准中,这就是 make_unique 的用途。 请展示一个完整的例子来说明问题。 【参考方案1】:

好吧,#define 是,恕我直言,这是一个大问题,因为它不遵守范围规则,而且它们会进行简单的文本替换,有时会产生令人惊讶的结果。当我需要完成某事时,我认为预处理器宏是最后的手段。

最好定义一个像make_shared 这样返回unique_ptr&lt;T&gt; 的模板。这是允许的,因为您可以将其移动到位。

auto a_drawable = make_unique<Drawable>(a, b, c);

template <typename T, typename... Args>
::std::unique_ptr<T> make_unique(Args&&... args)

    return ::std::unique_ptr<T>new T(::std::forward<Args>(args)...);

比宏更干净,它适用于任何非数组类型。这是一个问题。它也可以用于数组类型,但该代码有点复杂,我不会重复它,我只是指出一个有用的评论者推荐给我的答案:

make_unique and perfect forwarding

至于为什么在使用宏时会出现错误,我不确定。看起来您在某些上下文中使用宏,结果变成了const ::std::unique_ptr&lt;Drawable&gt; &amp;,然后尝试将其构造为不同的pDrawable。这行不通。为什么会这样,我不知道。这主要取决于您使用宏的上下文,而您尚未提供。

这只是突出了我的第一点。宏之所以很难看,原因之一是它们只是简单的文本替换,而且它们的含义会根据上下文而改变。

【讨论】:

哦,我很高兴我想出了一个几乎与 Herb Sutter 相同的 make_unique 版本,甚至都不知道他的。这是一个如此简单明了的功能,不过这并不令人意外。 有趣的是,你们都忘了处理char[]。 ***.com/a/13512344/845092 @MooingDuck - 哎呀! 是的,我们都做到了。人们分配数组并有一个unique_ptr 指向它们?!为什么,这是谁干的?! 我想不出有什么理由使用标准的make_unique。 (可能需要 C 与 malloc/free 互操作,但不能为此使用 make_unique @MooingDuck - 我也想不出理由。 unique_ptr 根本不支持 operator []。所以真正唯一有用的唯一数组句柄类型是::std::vector。是的,与 malloc/free 的互操作可能很好,您可以使用自定义删除器完成此操作,但您不能使用 make_unique【参考方案2】:

答案:

确保您确实使用了宏,一切都会好起来的。

显然,为了验证#define 宏,VC++ 会检查您对宏的实际使用情况。如果编译的宏没有实际使用,VC++ 会尝试“理解”它,并会抛出编译器错误。

神奇的是,如果我添加:

pDrawable myDraw = newDrawable();

在我上面的代码之后,错误消失了。

很抱歉浪费了大家的时间。至少这启发了我阅读以下文章:

http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

【讨论】:

以上是关于为啥不使用#define 来隐藏unique_ptr ugliness 在这里工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 Spring Boot/Thymeleaf 按钮会隐藏我的数据或根本不起作用?

为啥会出现这个错误:Gulp 中的“require is not defined”?

为啥Java使用-D来表示系统属性?

为啥我的 UITextView 文本从开始时不显示并隐藏在导航栏下

为啥有人使用 define(['jquery'...], function($...)... [重复]

为啥我的 UINavigationbar 被隐藏了?