2014-01-21 4 views
0

Я реализую std::optional, но столкнулся с одним из своих copy constructors.Как реализовать конструктор копирования std :: optional?

Вот набросок моей реализации:

#include <type_traits> 

template<typename T> 
class optional 
{ 
    public: 
    constexpr optional() 
     : m_is_engaged(false) 
    {} 

    constexpr optional(const optional &other) 
     : m_is_engaged(false) 
    { 
     operator=(other); 
    } 

    constexpr optional &operator=(const optional &other) 
    { 
     if(other.m_is_engaged) 
     { 
     return operator=(*other); 
     } 
     else if(m_is_engaged) 
     { 
     // destroy the contained object 
     (**this).~T(); 
     m_is_engaged = false; 
     } 

     return *this; 
    } 

    template<typename U> 
    optional &operator=(U &&value) 
    { 
     if(m_is_engaged) 
     { 
     operator*() = value; 
     } 
     else 
     { 
     new(operator->()) T(value); 
     m_is_engaged = true; 
     } 

     return *this; 
    } 

    T* operator->() 
    { 
     return reinterpret_cast<T*>(&m_data); 
    } 

    T &operator*() 
    { 
     return *operator->(); 
    } 

    private: 
    bool m_is_engaged; 
    typename std::aligned_storage<sizeof(T),alignof(T)>::type m_data; 
}; 

#include <tuple> 

int main() 
{ 
    optional<std::tuple<float, float, float>> opt; 

    opt = std::make_tuple(1.f, 2.f, 3.f); 

    return 0; 
} 

Проблема заключается в том, что компилятор жалуется, что optional «s constexpr конструктор не имеет пустое тело:

$ g++ -std=c++11 test.cpp 
test.cpp: In copy constructor ‘constexpr optional<T>::optional(const optional<T>&)’: 
test.cpp:15:5: error: constexpr constructor does not have empty body 
    } 
    ^

Я не конечно, как инициализировать optional::m_data в противном случае, и я не смог найти ссылку реализации в Интернете (boost::optional, по-видимому, не использует constexpr).

Любые предложения?

+2

Вы заметили в своей ссылке, что перемещение и копирование ctor не отмечены 'constexpr'? –

+0

Ha! Неа. Спасибо :) –

+0

Копаясь в [предложении] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3672.html), они также говорят об этом: «По-прежнему возможно чтобы сделать деструктор тривиальным для T, которые сами предоставляют тривиальный деструктор, и мы знаем, что возможна эффективная реализация такого дополнительного с интерфейсом времени компиляции - **, за исключением конструктора копирования и конструктора перемещения ** -. –

ответ

2

В C++ 11 функций и конструкторов, обозначенных как constexpr, очень ограничены в том, что они могут делать. В случае конструкторов, оно не может содержать в основном ничего, кроме static_assert, typedef или с помощью деклараций или с помощью директив, что исключает вызов operator= внутри тела конструктора.

Смежные вопросы