其他分享
首页 > 其他分享> > c – 在decltype()或operator noexcept()上下文中使用new new on nullptr

c – 在decltype()或operator noexcept()上下文中使用new new on nullptr

作者:互联网

是否允许标准编写decltype(:: new(nullptr)T(std :: declval< Args>()…))或noexcept(:: new(nullptr)T(std :: declval< Args) &GT()...))?特别感兴趣的是在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 * >{});

Disabler typename = decltype(S(std :: declval< T>()))需要存在析构函数,但不需要放置新的.

然而,无法评估decltype和运算符的背景,我不知道是否符合标准.因为编译器可能证明测试表达式的100%incorectness.

解决方法:

在标准的所有已发布版本中,可以将空指针传递给placement new,并且编译器需要处理该情况,因此如果它调用:: operator new(size_t,void *)为null,则代码是正常的指针.

但是,一个类可能重载了operator new(size_t,nullptr_t),在这种情况下你的表达式会使用它,因此你无法准确知道会发生什么(例如它可能被删除,或者它可能是noexcept(false)) .

在C17的工作草案中,如果保留的放置分配函数返回null,则它是未定义的行为(这在a question I asked here and on the committee lists引起的讨论之后发生了变化).目前尚不清楚这是否意味着它实际上被调用并返回null,或者甚至您的使用是否未定义.

我宁愿不冒险,也会使用更明确表达意图的东西.因为你要做的是测试构造(但不是破坏)是否可以抛出,通过使用一个不会抛出的新表达式,准确地说,并使用new(std :: nothrow),或者使用一个使用的表达式void *,不可证明是空指针:new(std :: declval< void *>()).

当您测试的属性与nullptr无关时,这可以避免因使用nullptr而导致的混淆.涉及nullptr只会使事情复杂化,让读者想知道nullptr的使用是否重要,或者你是否只是懒惰并将其用作“某些void *指针值”的简写.

标签:noexcept,c,c11,c14,decltype
来源: https://codeday.me/bug/20190829/1761719.html