[英]std::in_place_t and friends in C++17
As of the time of writing, cppreference gives a reasonably simple definition of the std::in_place_t
family: 截至编写本文时,cppreference给出了std::in_place_t
系列的一个相当简单的定义 :
struct in_place_t {
explicit in_place_t() = default;
};
inline constexpr std::in_place_t in_place{};
template <class T>
struct in_place_type_t {
explicit in_place_type_t() = default;
};
template <class T>
inline constexpr std::in_place_type_t<T> in_place_type{};
template <size_t I> struct in_place_index_t {
explicit in_place_index_t() = default;
};
template <size_t I>
inline constexpr in_place_index_t<I> in_place_index{};
However, the latest draft of the C++17 standard linked from isocpp.org has a rather more complicated definition (section 20.2.7, page 536): 但是, 从isocpp.org链接的最新C ++ 17标准草案有一个相当复杂的定义(第20.2.7节,第536页):
struct in_place_tag {
in_place_tag() = delete;
};
using in_place_t = in_place_tag(&)(unspecified );
template <class T>
using in_place_type_t = in_place_tag(&)(unspecified <T>);
template <size_t I>
using in_place_index_t = in_place_tag(&)(unspecified <I>);
in_place_tag in_place(unspecified );
template <class T>
in_place_tag in_place(unspecified <T>);
template <size_t I>
in_place_tag in_place(unspecified <I>);
The first version is simple and easy to understand, but second version is quite opaque to me. 第一个版本简单易懂,但第二个版本对我来说非常不透明。 So, questions: 所以,问题:
Which version is correct, post-Issaqua (November 2016)? 哪个版本是正确的,在Issaqua之后(2016年11月)? (Presumably the second, but it's possible that N4606 hasn't yet been updated after the latest meeting and cppreference has.) (可能是第二个,但是在最新的会议和cppreference之后,N4606可能还没有更新。)
Clearly this has changed at some point in time; 显然,这在某个时间点发生了变化; does anyone have a link to a paper mentioning the change? 有没有人提到一篇提到变化的论文?
Most importantly, can anyone explain how the second version is intended to work? 最重要的是,任何人都可以解释第二个版本的工作原理吗? What would a sample implementation look like? 示例实现是什么样的?
The first version is the right one, currently, and will in all likelihood be the one ending up in C++17. 目前,第一个版本是正确的版本,并且很可能是以C ++ 17结尾的版本。
The second version was an attempt to allow one to write in_place
everywhere, with nothing, with a type, or with an index: 第二个版本试图允许一个人在in_place
地方写入in_place
,没有任何东西,有类型或索引:
std::optional<int> o(std::in_place, 1);
std::any a(std::in_place<int>, 1);
std::variant<int, int> v(std::in_place<0>, 1);
The only way to make this syntax work is to make in_place
an overloaded function, and that also requires making in_place*_t
aliases for references to functions. 使这种语法有效的唯一方法是使in_place
成为重载函数,并且还需要为函数引用创建in_place*_t
别名。 There's no real implementation difference otherwise - the in_place
functions aren't meant to be called, they exist only so that a reference to them can be passed around as a tag and match the corresponding _t
types. 否则没有真正的实现差异 - in_place
函数不是要调用的,它们只是存在,以便对它们的引用可以作为标记传递并匹配相应的_t
类型。
Nonetheless it was too clever and caused its own problems (for instance, unlike plain tag types, they don't respond well to being decay
'd, and plain std::in_place
, being an overloaded function name, misbehaves with perfect forwarders: std::optional<std::optional<int>> o(std::in_place, std::in_place);
doesn't work because the compiler can't resolve the second std::in_place
), so it got backed out in Issaquah, and now you have to write 尽管如此,它太聪明并且引起了它自己的问题(例如,与普通标签类型不同,它们对decay
没有很好的反应,而普通的std::in_place
是一个重载的函数名称,与完美的转发器行为不端: std::optional<std::optional<int>> o(std::in_place, std::in_place);
不起作用,因为编译器无法解析第二个std::in_place
),所以它被取消了Issaquah,现在你必须写
std::optional<int> o(std::in_place, 1);
std::any a(std::in_place_type<int>, 1);
std::variant<int, int> v(std::in_place_index<0>, 1);
A little less pretty, but more sane. 不太漂亮,但更健全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.