为什么<T> LLVM 中的预期为 Expect&&... 实现两个构造函数<T>?
Why does Expected<T> in LLVM implement two constructors for Expected<T>&&?
Expected<T>
在 llvm/Support/Error.h 中实现。它是一个标记的联合,持有T
或Error
。
Expected<T>
是一个类型为T
的模板类:
template <class T> class LLVM_NODISCARD Expected
但是这两个构造函数真的让我感到困惑:
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// must be convertible to T.
template <class OtherT>
Expected(Expected<OtherT> &&Other,
typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
* = nullptr) {
moveConstruct(std::move(Other));
}
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// isn't convertible to T.
template <class OtherT>
explicit Expected(
Expected<OtherT> &&Other,
typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
nullptr) {
moveConstruct(std::move(Other));
}
为什么Expected<T>
为同一个实现重复两个构造?为什么它不这样做?
template <class OtherT>
Expected(Expected<OtherT>&& Other) { moveConstruct(std::move(Other));}
因为根据提案,该构造函数是有条件显式的。这意味着构造函数仅在满足某些条件时才显式(此处为T
和OtherT
的可转换性(。
C++在 C++20 之前没有此功能的机制(如explicit(condition)
(。因此,实现需要使用其他一些机制,例如定义两个不同的构造函数(一个显式构造函数和另一个转换构造函数(,并确保根据条件选择正确的构造函数。这通常是在std::enable_if
的帮助下通过SFINAE完成的,在那里病情得到解决。
自 C++20 起,应该有一个条件版本的explicit
说明符。使用单个定义,实现会容易得多:
template <class OtherT>
explicit(!std::is_convertible_v<OtherT, T>)
Expected(Expected<OtherT> &&Other)
{
moveConstruct(std::move(Other));
}
要理解这一点,我们应该从std::is_convertible
开始。根据 cpp 偏好:
如果虚函数定义
To test() { return std::declval<From>(); }
格式正确(即,可以使用隐式转换将std::declval<From>()
转换为To
,或者From
和To
都可能是 cv 限定的 void(,则提供等于true
的成员常量值。否则,值为false
。出于此检查的目的,在 return 语句中使用std::declval
不被视为 odr 使用。访问检查的执行方式与从与任一类型无关的上下文中执行。仅考虑 return 语句中表达式的直接上下文的有效性(包括对返回类型的转换(。
这里重要的部分是它只检查隐式转换。因此,OP 中的两个实现的意思是,如果OtherT
可隐式转换为T
,则expected<OtherT>
可隐式转换为expected<T>
。如果OtherT
需要显式强制转换来T
,则Expected<OtherT>
需要显式强制转换Expected<T>
。
以下是隐式和显式强制转换及其Expected
对应项的示例
int x;
long int y = x; // implicit cast ok
Expected<int> ex;
Expected<long int> ey = ex; // also ok
void* v_ptr;
int* i_ptr = static_cast<int*>(v_ptr); // explicit cast required
Expected<void*> ev_ptr;
auto ei_ptr = static_cast<Expected<int*>>(ev_ptr); // also required
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中