Ori*_*ent 3 c++ decltype noexcept c++11 c++14
是否允许标准书写decltype(::new (nullptr) T(std::declval< Args >()...))或noexcept(::new (nullptr) T(std::declval< Args >()...))?特别感兴趣的new是nullptr正确性.考虑以下代码:
#include <type_traits>
#include <utility>
struct S { S(int) { ; } ~S() = delete; };
struct A
{
template< typename T,
bool is_noexcept = noexcept(::new (nullptr) S(std::declval< T >())) >
A(T && x) noexcept(is_noexcept)
: s(new S(std::forward< T >(x)))
{ ; }
S * s;
};
static_assert(std::is_constructible< A, int >{});
static_assert(!std::is_constructible< A, void * >{});
Run Code Online (Sandbox Code Playgroud)
Disabler typename = decltype(S(std::declval< T >()))需要存在析构函数,但不需要放置new.
尽管如此decltype,noexcept我还是对运营商的背景和运营商不以为然.因为编译器可能证明测试表达式的100%incorectness.
在标准的所有已发布版本中,可以将空指针传递给placement new,并且编译器需要处理这种情况,因此如果::operator new(size_t, void*)使用空指针调用代码就可以了.
但是,一个类可能会重载,operator new(size_t, nullptr_t)在这种情况下你的表达式会使用它,因此你无法准确知道会发生什么(例如它可能被删除,或者它可能是noexcept(false)).
在C++ 17的工作草案中,如果保留的放置分配函数返回null,则它是未定义的行为(这是在我在此处和委员会列表中提出的问题引起的讨论后更改的).目前尚不清楚这是否意味着它实际上被调用并返回null,或者甚至您的使用是否未定义.
我宁愿不冒险,也会使用更明确表达意图的东西.因为你要做的是测试构造(但不是破坏)是否可以抛出,通过使用一个new不会抛出的表达式,准确地说,并使用new(std::nothrow),或者使用一个使用void*不可证明是空指针的表达式:new (std::declval<void*>()).
这可以避免因nullptr您正在测试的属性与之无关而使用时造成的混淆nullptr.nullptr通过让读者想知道是否使用nullptr是重要的,或者你只是懒惰并将其用作"某些void*指针值" 的简写,让涉及复杂的事情变得复杂.
| 归档时间: |
|
| 查看次数: |
328 次 |
| 最近记录: |