[英]optional std::nullopt_t implementation in libcxx
Clang implements std::nullopt_t
this way: Clang
std::nullopt_t
这种方式实现std::nullopt_t
:
struct nullopt_t
{
explicit constexpr nullopt_t(int) noexcept {}
};
constexpr nullopt_t nullopt{0};
Why not simply: 为什么不简单:
struct nullopt_t{};
constexpr nullopt_t nullopt{};
? ?
According to cppreference : 根据cppreference :
std::nullopt_t
must be a LiteralType and cannot have a default constructor.std::nullopt_t
必须是LiteralType,并且不能有默认构造函数。 It must have a constexpr constructor that takes some implementation-defined literal type.它必须有一个constexpr构造函数,它采用一些实现定义的文字类型。
... so if Clang implemented nullopt_t
as you suggested, it wouldn't meet the requirements. ...所以如果Clang按照你的建议实现了
nullopt_t
,那就不符合要求了。 Now, if you are wondering why those requirements exist (a different question), the answer is: 现在,如果您想知道为什么存在这些要求(一个不同的问题),答案是:
nullopt_t
is not DefaultConstructible to support bothop = {};
nullopt_t
不是DefaultConstructible以支持op = {};
andop = nullopt;
和
op = nullopt;
as the syntax for disengaging an optional object.作为脱离可选对象的语法。
As mentioned on std::nullopt_t : 如std :: nullopt_t中所述 :
Notes
笔记
nullopt_t
is notDefaultConstructible
to support bothop = {};
nullopt_t
不是DefaultConstructible
以支持op = {};
andop = nullopt;
和
op = nullopt;
as the syntax for disengaging an optional object.作为脱离可选对象的语法。
Now test this with your implementation: 现在用你的实现测试一下:
struct nullopt_t { };
template <typename T>
struct optional {
optional &operator=(nullopt_t);
optional &operator=(const optional &);
optional &operator=(optional &&);
template <typename U>
optional &operator=(U &&);
};
int main() {
optional<int> oi;
oi = {};
}
This fails, because the call to operator=
is ambiguous. 这失败了,因为对
operator=
的调用是不明确的。 It could be an attempt to call operator=(nullopt_t)
, or it could be an attempt to call operator=(optional &&)
, and there is no language rule to resolve this ambiguity. 它可能是尝试调用
operator=(nullopt_t)
,或者它可能是尝试调用operator=(optional &&)
,并且没有语言规则来解决这种歧义。
Therefore, unless there's a change to the language rules, or oi = {};
因此,除非语言规则发生变化,否则
oi = {};
no longer needs to be valid, either nullopt_t
or optional
needs to not be default-constructible, and nullopt_t
is the logical choice for that. 不再需要有效,
nullopt_t
或者optional
不需要是default-constructible,而nullopt_t
是它的逻辑选择。
Others have explained why struct nullopt_t {};
其他人解释了为什么
struct nullopt_t {};
is insufficient. 不够。 But there are at least two alternative solutions that are still simpler than the ones currently ensconced in libc++ and libstdc++.
但是至少有两种替代解决方案仍然比目前在libc ++和libstdc ++中实现的解决方案更简单。
(Here's some test code: http://melpon.org/wandbox/permlink/HnFXRjLyqi4s4ikv ) (这是一些测试代码: http : //melpon.org/wandbox/permlink/HnFXRjLyqi4s4ikv )
Here are the alternatives, in increasing order of paranoia: 以下是偏执狂递增顺序的替代方案:
struct nullopt_t { constexpr explicit nullopt_t() {} };
constexpr nullopt_t nullopt{};
struct nullopt_t { constexpr explicit nullopt_t(int) {} };
constexpr nullopt_t nullopt{0};
struct nullopt_t {
enum class secret { tag };
explicit constexpr nullopt_t(secret) { }
};
constexpr nullopt_t nullopt{nullopt_t::secret::tag};
struct nullopt_t {
struct secret_tag { explicit secret_tag() = default; };
constexpr explicit nullopt_t(secret_tag, secret_tag) noexcept {}
};
constexpr nullopt_t nullopt{nullopt_t::secret_tag{}, nullopt_t::secret_tag{}};
Any one of these alternatives (even Option 1, as far as I know) would suffice to make the assignment o = {}
unambiguous. 这些备选方案中的任何一个(即使是备选方案1,据我所知)都足以使赋值
o = {}
明确无误。 I don't know why both libc++ and libstdc++ go beyond that solution — and notice that libc++ goes so far as to create a two-argument constructor! 我不知道为什么libc ++和libstdc ++都超越了这个解决方案 - 并注意到libc ++甚至创建了一个双参数构造函数!
If anyone knows the reason for libc++'s increased paranoia, I'd love to hear it; 如果有人知道libc ++增加妄想症的原因,我很乐意听到它; please create an answer and/or leave a comment below.
请在下面创建答案和/或发表评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.