由于保证复制省略,std::declval是否已过时?

标准库实用程序declval被定义为:

template<class T> add_rvalue_reference_t<T> declval() noexcept;

在这里添加右值引用似乎是一个好主意,如果您考虑一下C++11 中引入的语言:返回值涉及一个临时值,该值随后被移出。现在C++17引入了保证复制省略,这不再适用。正如cppref所说:

纯右值和临时值的 C++17 核心语言规范与早期 C++ 修订版的核心语言规范根本不同:不再有临时值可以复制/移动。描述 C++17 机制的另一种方法是“非物化值传递”:返回和使用纯右值,而不会物化临时值。

这对其他以declval. 看看这个例子(在Godbolt.org上查看):

#include <type_traits>

struct Class {
    explicit Class() noexcept {}    
    Class& operator=(Class&&) noexcept = delete;
};

Class getClass() {
    return Class();
}

void test() noexcept {
    Class c{getClass()}; // succeeds in C++17 because of guaranteed copy elision
}

static_assert(std::is_constructible<Class, Class>::value); // fails because move ctor is deleted

这里我们有一个不可移动的类。由于保证复制省略,它可以从函数返回,然后在test(). 然而,is_construtible类型特征表明这是不可能的,因为它是根据以下定义的declval

is_­constructible<T, Args...>当且仅当以下变量定义对于某些发明变量是格式良好的时,才应满足模板特化的谓词条件
t
T t(declval<Args>()...);

因此,在我们的示例中,类型特征声明 ifClass可以从返回 的假设函数构造Class&&test()任何当前类型特征都无法预测是否允许该行,尽管命名表明is_constructible确实如此。

这意味着,在保证复制省略实际上可以挽救这一天的所有情况下,is_constructible通过告诉我们“它可以在 C++11 中构造吗?”的答案来误导我们。

这不仅限于is_constructible. 扩展上面的例子(在godbolt.org上查看)

void consume(Class) noexcept {}

void test2() {
    consume(getClass()); // succeeds in C++17 because of guaranteed copy elision
}

static_assert(std::is_invocable<decltype(consume), Class>::value); // fails because move ctor is deleted

这表明它is_invocable受到了类似的影响。

对此最直接的解决方案是更改declval

template<class T> T declval_cpp17() noexcept;

这是 C++17(以及后续,即 C++20)标准中的缺陷吗?还是我错过了点,为什么这些declvalis_constructibleis_invocable规范仍在我们可以有最好的解决方案?

回答

然而,is_construtible类型特征表明这是不可能的,因为它是根据以下定义的declval

Class不能从它自己类型的实例构造。所以is_constructible不应该说它是。

如果类型T满足is_constructible<T, T>,则期望您可以创建一个T给定类型的对象T而不是您可以T从类型的纯右值中创建一个特定的对象T。这不是使用的怪癖declval;这就是问题的is_constructible意思。

你的建议是,它is_constructible应该回答一个与它打算回答的问题不同的问题。应该注意的是,保证省略意味着所有类型都可以从其自身类型的纯右值“构造”。所以如果这就是你想问的,那么你已经有了答案。

  • @Tobi: I think the way to think about it is that use of a prvalue to initialize something is not *construction* at all.

以上是由于保证复制省略,std::declval是否已过时?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>