我很好奇std::is_invocable_r的定义,以及它如何与不可移动类型交互。基于我对它应该模仿的语言规则的理解,它在C 20模式下的clang下的libc实现似乎是错误的,所以我想知道我的理解有什么不正确之处。
假设我们有一个不能移动或复制构造的类型,以及一个返回它的函数:
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
对象(我认为是由于复制省略规则):
CantMove cant_move = MakeCantMove();
类型特征同意函数是可调用的,并返回CantMove
:
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中,在clang下是这样的:
static_assert(!std::is_invocable_r_v<CantMove, F>);
std::is invocable\r
的定义是
表达式INVOKE
使用
调用
定义
调用
而
INVOKE
定义(在本例中)为简单的MakeCantMove()
。但关于是否可能进行隐式转换的定义是:
表达式
E
可以隐式转换为类型T
当且仅当声明T=E
是格式良好的,对于一些发明的临时变量t
([dcl.init])。
但我们在上面看到了
CantMove cant_move=MakeCantMove()
。那么,clang接受这个初始化是错误的,还是
std::is_invocable_r_v
的实现是错误的?还是我对标准的解读有误?
作为记录,我关心这个问题的原因是,像
std::move_only_function
(我正在使用一个高级端口来连接这个函数的C20)这样的类型,其成员的重载集受到std::is_invocable_r_v
的限制,我发现不可能有效地处理返回这种不移动类型的函数。这是故意的吗?如果是,为什么?
匿名用户
那么,clang接受这个初始化是错误的,还是std::is_invocable_r_v
的实现是错误的?
这是libc的一个bug。在实现<代码>is_invocable_r时,它使用<代码>is_convertible来确定结果是否可以隐式转换为<代码>T,这是不正确的,因为<代码>is convertible_v
值得注意的是,libstdc和MSVC-STL都有关于这个问题的错误报告,这些报告已经修复。
问题内容: 我在某处读到,函数应始终仅返回一种类型,因此以下代码被视为错误代码: 我想更好的解决方案是 返回None然后创建一个新的空元组不是更便宜的内存明智的选择吗?或者即使在较大的项目中,这种时差也太小而无法引起注意? 问题答案: 为什么函数应该返回一致类型的值?满足以下两个规则。 规则1-函数具有“类型”-输入映射到输出。它必须返回一致的结果类型,否则它不是函数。一团糟。 从数学上讲,我们说
允许您执行以下操作: 但不是这个: 可能是因为返回类型不是函数签名的一部分。但是是一个类类型,它被赋予一个返回类型,并且知道构造它的函数对象的返回类型。所以这里可能有编译器错误。 为什么没有编译器错误?
我有以下示例代码,简化为基本代码,它使用GCC6.1、GCC7.0head和Visual Studio 2015/2017 RC编译,但不使用任何clang版本。 clang告诉我:prog.cc:12:34:error:'_p'是'outer::foo'返回std::make_tuple(c_p...)的私有成员;
我知道了从< code>std::async返回的< code>future具有某种特殊共享状态的原因,通过这种状态,< code >等待返回的future发生在future的析构函数中。但是当我们使用< code>std::pakaged_task时,它的未来不会表现出同样的行为。要完成打包的任务,必须从< code>packaged_task显式调用< code>future对象上的< cod
问题内容: 我有一个模块分开的应用程序。有几个实体和CSV模块。CSV模块仅支持struct(Entity),但我想使CSV模块可与任何类型的实体一起使用。现在,它的工作方式如下:Csv模块从通道接收数据并将其严格转换为struct。我如何实现动态返回类型,因此它可以与任何类型的Entity一起使用,而不仅限于 问题答案: 快速/肮脏的解决方案: 返回接口{},但是您最终欺骗了编译器,而类型检查的