std::launder alternative pre c++17

时间:2019-01-18 18:52:21

标签: c++ c++14 language-lawyer c++17 stdlaunder

It is like std::optional, but doesn't store an extra bool. User has to make sure to access only after initializing.

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;
};

If you are wondering why I need such an obscure datastructure, check here: https://gitlab.com/balki/linkedlist/tree/master

Question

  1. Is it ok to ignore std::launder? I guess not.
  2. Since std::launder is available only in c++17, how to implement above class in c++14? boost::optional and std::experimental::optional should have needed similar feature or did they use compiler specific magic?

Note: It is easy to miss, the type is declared as union. Which means constructor of T is really not called. Ref: https://gcc.godbolt.org/z/EVpfSN

1 个答案:

答案 0 :(得分:3)

不,您不能。提出std::launder的原因之一是std::optional在C ++ 14中无法实现。您可以参考this discussion了解详情。

另一方面,您可以不使用constexpr来实现。想法是将缓冲区与reinterpret_cast一起使用,因为reinterpret_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;
};

boost::optional uses this idea的实现,并且没有实现constexpr语义(有关详细信息,您可以参考其source code)。