假设class
包含一个由嵌套定义的类型,该嵌套using
的析构函数需要显式调用。是否有必要用于using
创建不包含名称空间分隔符(::
)的本地类型?
在这个人为的示例中,我想调用A::WeakPtr
的析构函数,例如:
wp->~A::WeakPtr();
而不是像:
using AWeakPtr = A::WeakPtr;
wp->~AWeakPtr()
这可行吗?这是一个完整的例子。
#include <cstdlib>
#include <iostream>
#include <memory>
struct A : std::enable_shared_from_this<A> {
using SharedPtr = std::shared_ptr<A>;
using WeakPtr = std::weak_ptr<A>;
A() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
~A() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int
main() {
{
std::unique_ptr<A::WeakPtr, void(*)(void*)>
uwp(static_cast<A::WeakPtr*>(std::malloc(sizeof(A::WeakPtr))), std::free);
A::WeakPtr* wp = uwp.get();
{
auto sp = std::make_shared<A>();
new(wp) A::WeakPtr(sp);
if (wp->lock())
std::cout << "Locked\n";
else
std::cout << "Unlocked\n";
}
if (wp->lock())
std::cerr << "EUNPOSSIBLE\n";
else
std::cout << "Unable to obtain lock\n";
// Need the following 'using' statement because the following is invalid syntax:
// wp->~A::WeakPtr();
using AWeakPtr = A::WeakPtr;
wp->~AWeakPtr();
// Is there a way to call A::WeakPtr without the using statement?
}
std::cout << "memory held by uwp has been free(3)'ed\n";
}
似乎应该有一种方法可以打败分散在某处的::
名称空间分隔符typename
,但似乎不可能。显然,如果不可能的话,这不是世界末日,但是我的古玩正在使我变得更好。
更新
正如@DanielFrey和@DyP的绝妙答案所暗示的那样,正确的语法确实是
wp->A::WeakPtr::~WeakPtr();
但这不起作用,并且是clang ++中的错误(#12350)(截至2013-09-28)。
在此处使用限定ID的析构函数调用必须包括:
postfix-expression ->
嵌套名称说明符 ~
类名称 ()
所述后缀表达式这里wp
,和之后的部分->
形成单 合格-ID(W / O的括号)。
在语法上,以下也是可能的:
postfix-expression ->
嵌套名称说明符 ~
decltype-specifier ()
但是,[expr.prim.general] / 9中明确禁止使用第二种形式:
该格式
~ decltype-specifier
还表示析构函数,但不得在qualified-id中用作unqualified -id。
第一种形式的类名也可以是typedef-name [class.name] / 5:
命名类类型或其cv限定版本的typedef-name(7.1.3)也是class-name。
对于此的查找类名后~
,有一个在[basic.lookup.qual]一个特殊的名字查找规则/ 5:
类似地,采用以下形式的限定ID:
nested-name-specifier opt class-name:: ~
class-name,在与第一个相同的作用域中查找
第二个类名。
这意味着,第二WeakPtr
中A::WeakPtr :: ~WeakPtr
应该可以找到。这是一个为类命名的typedef名称,因此是一个class-name,并在的范围内进行了查找A
。gcc遵循此规则,而clang ++ 3.4则不这样做。
因此,wp->A::WeakPtr :: ~WeakPtr();
如建议由丹尼尔·弗雷(和我的第一个,删除评论/猜测)应该工作。
替代方法:
使用辅助功能:
template<class T>
void destroy(T& t)
{ t.~T(); }
使用w / oaqualified -id的decltype-specifier。这是一个棘手的问题,因为类型为,所以会产生一个左值。但是,我们可以将表达式转换为prvalue以摆脱引用:decltype(*wp)
A::WeakPtr&
*wp
wp->~decltype((A::WeakPtr)*wp)();
// alternatively, w/o explicitly mentioning the type:
wp->~decltype((std::remove_pointer<decltype(wp)>::type)*wp)();
// simpler, using a helper function again:
template<class T> T helper(T const&);
wp->~decltype(helper(*wp))();
生产:
从函数调用[expr.post] / 1开始:
postfix-expression
(
表达式列表opt)
这里的postfix-expression是通过以下方式产生的:
后缀表达式
-> template
opt id表达式
此postfix-expression此处映射到wp
(中的wp->~something()
)。
id表达式包含析构函数“名称” [expr.prim.general]:
id-expression:
不合格ID
合格ID
我们这里确实需要一个合格的ID,因此[expr.prim.general] / 8:
合格ID:
嵌套名称说明符template
opt 不合格ID
::
标识符
::
operator-id
::
-literal-operator-id
::
template-id
只有第一个感兴趣,因此我们看一下unqualid-id:
不合格ID:
标识符
运算符功能ID
转换功能ID
文字运算符ID
~
类名
~
decltype-specifier
模板ID
其中带有a的两个~
可用于调用析构函数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句