gpt4 book ai didi

c++ - std::declval 是否因为保证复制省略而过时?

转载 作者:行者123 更新时间:2023-12-04 00:49:23 27 4
gpt4 key购买 nike

标准库实用程序 declvaldefined作为:

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

C++11 中引入右值引用似乎是个好主意:返回一个值涉及临时的,后来被移走了。现在 C++17 引入了保证复制省略,这不再适用。作为cppref说:

C++17 core language specification of prvalues and temporaries isfundamentally different from that of the earlier C++ revisions: thereis no longer a temporary to copy/move from. Another way to describeC++17 mechanics is "unmaterialized value passing": prvalues arereturned and used without ever materializing a temporary.

这对根据 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

这里我们有一个nonmovable类。由于保证复制省略,它可以从函数返回,然后在 test() 中本地具体化。 .然而 is_construtible类型特征表明这是不可能的,因为它是 defineddeclval 方面:

The predicate condition for a template specializationis_­constructible<T, Args...> shall be satisfied if and only if thefollowing variable definition would be well-formed for some inventedvariable t:
T t(declval<Args>()...);

因此在我们的示例中,类型特征表明 if Class可以从返回 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)标准中的缺陷吗?或者我错过了为什么这些 declval , is_constructibleis_invocable规范仍然是我们可以拥有的最佳解决方案吗?

最佳答案

However the is_construtible type trait suggests this is not possible, because it is defined in terms of declval:

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

如果类型 T满足is_constructible<T, T> ,期望你可以做一个 T给定一个 T 类型的对象,不是你可以做一个T特别是来自 T 类型的纯右值.这不是使用 declval 的怪癖;是什么问题is_constructible意味着。

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

关于c++ - std::declval 是否因为保证复制省略而过时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67826261/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com