1

以下隐藏 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 不编译

编辑2

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

4

2 回答 2

14

好吧,#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)...)};
}

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

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

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

于 2013-02-07T00:33:33.780 回答
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

于 2013-02-07T07:03:26.487 回答