首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么std::is_invocable_r拒绝返回不可移动类型的函数?

为什么std::is_invocable_r拒绝返回不可移动类型的函数?
EN

Stack Overflow用户
提问于 2022-05-09 01:05:59
回答 1查看 627关注 0票数 13

我很好奇std::is_invocable_r的定义,以及它如何与不可移动的类型交互。基于我对它应该模仿的语言规则的理解,它在C++20模式下的clang实现似乎是错误的,所以我想知道我的理解有什么不正确的地方。

假设我们有一个不能移动或复制的类型,以及一个返回它的函数:

代码语言:javascript
运行
复制
struct CantMove {
  CantMove() = default;
  CantMove(CantMove&&) = delete;
};

static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);

CantMove MakeCantMove() { return CantMove(); }

然后可以调用该函数来初始化CantMove对象(我相信由于复制省略规则):

代码语言:javascript
运行
复制
CantMove cant_move = MakeCantMove();

并且类型特征一致认为函数是可调用的,并返回CantMove

代码语言:javascript
运行
复制
using F = decltype(MakeCantMove);
static_assert(std::is_invocable_v<F>);
static_assert(std::is_same_v<CantMove, std::invoke_result_t<F>>);

std::is_invocable_r表示,不可能调用它来产生一些可转换成CantMove的东西,至少在C++20中是这样的:

代码语言:javascript
运行
复制
static_assert(!std::is_invocable_r_v<CantMove, F>);

定义 of std::is_invocable_r

如果将表达式INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...)视为未计算的操作数,则该表达式的格式很好。

INVOKE<R>已定义作为

INVOKE<R>(f, t1, t2, …, tN)定义为. INVOKE(f, t1, t2, …, tN)隐式转换为R

INVOKE 已定义 (在本例中)为简单的MakeCantMove()。但是,关于是否可能进行隐式转换的定义说:

表达式E可以隐式转换为类型T当且仅当声明T t=E;格式良好时,对于某些发明的临时变量t (dcl.init)。

但是我们在上面看到,CantMove cant_move = MakeCantMove();被编译器所接受。接受这个初始化是错误的,还是std::is_invocable_r_v 的实现是错的?还是我对标准的解读错了?

作为记录,我关心这个问题的原因是,像std::move_only_function这样的类型(我使用的是它的C++20的高级端口),其成员的重载设置是由std::is_invocable_r_v设置的,而且我发现不可能使用像这样返回非移动类型的函数。这是故意的吗?如果是的话,原因何在?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-09 02:03:21

那么,接受这个初始化是错误的还是std::is_invocable_r_v的实现是错的呢?

这是libc++的一个bug。在is_invocable_r中,它使用is_convertible来确定结果是否可以隐式转换为T,这是不正确的,因为is_convertible_v<T, T>是不可移动类型的false,在这种情况下,std::declval添加了对T的rvalue引用。

值得注意的是,libstdc++MSVC-STL都有关于此问题的错误报告,并且已经修复。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72166085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档