为啥不使用#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<T>
的模板。这是允许的,因为您可以将其移动到位。
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<Drawable> &
,然后尝试将其构造为不同的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”?
为啥我的 UITextView 文本从开始时不显示并隐藏在导航栏下