ほぼoptional。templateの練習して
#pragma once
#include <type_traits>
#include <assert.h>
template<typename T>
class LazyInit_Base{
public:
LazyInit_Base() : constructed_(false) {}
~LazyInit_Base() {
if(!isConstructed()) return;
static_cast<T*>((void*)(&seat_))->~T();
constructed_ = false;
}
T * operator->() const{
return static_cast<T*>((void*)(&seat_));
}
T & operator*() const{
return *static_cast<T*>((void*)(&seat_));
}
template<typename ...Args>
void construct(Args... args) {
assert(constructed_ == false);
new(&seat_) T(std::forward<Args>(args)...);
constructed_ = true;
}
bool isConstructed() const{
return constructed_;
}
explicit operator bool() const{
return isConstructed();
}
private:
bool constructed_;
typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type seat_;
};
template<
typename T,
bool IsCopyable = std::is_copy_assignable<typename std::remove_const<T>::type>::value && std::is_copy_constructible<typename std::remove_const<T>::type>::value
>
class LazyInit : public LazyInit_Base<T>{
public:
LazyInit() = default;
LazyInit(const LazyInit & rhs) {
construct(*rhs);
}
LazyInit & operator=(const LazyInit&) = delete;
template <typename U>
LazyInit(const LazyInit<U> & rhs) {
static_assert(std::is_convertible<U, T>::value == true, "U not convertible to T");
construct(*rhs);
}
};
template<typename T>
class LazyInit<T, false> : public LazyInit_Base<T>{
public:
LazyInit() = default;
LazyInit(const LazyInit&) = delete;
LazyInit(LazyInit &&) = delete;
LazyInit & operator=(const LazyInit&) = delete;
};