C++ std::洗槽替代方案c和x2B+;17
它类似于std::optional,但不存储额外的bool。用户必须确保仅在初始化后访问C++ std::洗槽替代方案c和x2B+;17,c++,c++14,language-lawyer,c++17,stdlaunder,C++,C++14,Language Lawyer,C++17,Stdlaunder,它类似于std::optional,但不存储额外的bool。用户必须确保仅在初始化后访问 template<class T> union FakeOptional { //Could be a normal struct in which case will need std::aligned storage object. FakeOptional(){} //Does not construct T template<class... Args>
template<class T>
union FakeOptional { //Could be a normal struct in which case will need std::aligned storage object.
FakeOptional(){} //Does not construct T
template<class... Args>
void emplace(Args&&... args){
new(&t) T{std::forward<Args&&>(args)...};
}
void reset(){
t.~T();
}
operator bool() const {
return true;
}
constexpr const T* operator->() const {
return std::launder(&t);
}
constexpr T* operator->() {
return std::launder(&t);
}
T t;
};
模板
union FAKEOPERTIONAL{//可以是一个普通结构,在这种情况下需要std::aligned存储对象。
FakeOptional(){}//不构造T
模板
空侵位(Args&…Args){
新建(&t)t{std::forward
问题:
忽略std::launder
可以吗?我想不行
由于std::launder
仅在c++17中可用,如何在c++14中实现上述类?boost::optional
和std::experimental::optional
应该需要类似的功能,或者它们是否使用了特定于编译器的魔法
注意:很容易错过,类型被声明为union
。这意味着T
的构造函数实际上没有被调用。Ref:不,您不能。提出std::launder
的原因之一是std::optional
在C++14中不可实现。有关详细信息,请参阅
另一方面,您可以在不使用constexpr
的情况下实现它。其思想是使用带有reinterpret\u cast
的缓冲区,因为reinterpret\u cast
的结果将始终引用新创建的对象(在C++17中仍然需要std::launder
,但在C++14中这是可以的)
template<class T>
struct FakeOptional {
FakeOptional(){}
template<class... Args>
void emplace(Args&&... args){
new(&storage) T{std::forward<Args&&>(args)...};
}
void reset(){
reinterpret_cast<T*>(&storage)->~T();
}
operator bool() const {
return true;
}
const T* operator->() const {
return reinterpret_cast<const T*>(&storage);
}
T* operator->() {
return reinterpret_cast<T*>(&storage);
}
std::aligned_storage_t<sizeof(T), alignof(T)> storage;
};
模板
结构FakeOptional{
FakeOptional(){}
模板
空侵位(Args&…Args){
new(&storage)T{std::forward,不实现constexpr
语义(您可以参考它的详细信息)。只需将new放入字节数组中即可+重新解释转换运算符bool()const{return true;}
…FakeOptional
。是的,听起来不错。@FrançoisAndrieux它是一个并集,而不是结构。因此它不是构造的。这就是这种类型的全部要点。避免默认构造,但只需分配足够的空间,以后可能会用到。@Nicolas,我正在使用一个并集。注意:union FakeOptional
它完全是一个构造对于编译器来说,你必须有编译器支持。你能做的最好的事情就是检查是否有\u内置的\u launder
或类似的东西。我想知道,在现在的编译器中,std::launder
是否是必要的。在这种情况下,如果常量成员没有随func而改变,Clang、GCC、MSVC或ICC都不会优化代码假设调用。这样我们就可以推断出std::launder
是不必要的。但是我们不能从一个例子中得出一条定律。你知道编译器进行优化的一个例子吗?这将证明你的方法是必要的,以及先前归纳推理的弱点。但是指针是“普通类型”正式地说,指针的字节副本就可以了!或者普通类型并不是真正的“普通”@Oliv当然,我的方法只在语言律师的方式下才有必要。对const/ref成员的限制,因此如果启用这种优化,一些旧代码可能会被破坏。我想这就是为什么这些编译器有点保守的原因之一。@curiousguy抱歉,我不明白你的意思。你为什么提到指针复制?@curiousguy Ohh的确,我忘记了C++引用中的const引用不是一个接口契约:(但是!const对象(包括成员SubEdEx)是一个契约,因为它禁止更改const对象的值。