/* * Copyright (C) 2014 Pavel Kirienko */ #pragma once #include #include #include namespace uavcan { template class LazyConstructor { unsigned char data_[sizeof(T)] __attribute__((aligned(16))); // TODO: compiler-independent alignment T* ptr_; void ensureConstructed() const { if (!ptr_) handleFatalError("LazyConstructor is not constructed"); } void ensureNotConstructed() const { if (ptr_) handleFatalError("LazyConstructor is already constructed"); } template struct ParamType { typedef const U& Type; }; template struct ParamType { typedef U& Type; }; #if __cplusplus > 201100 template struct ParamType { typedef U&& Type; }; #endif public: LazyConstructor() : ptr_(NULL) { std::fill(data_, data_ + sizeof(T), 0); } LazyConstructor(const LazyConstructor& rhs) : ptr_(NULL) { std::fill(data_, data_ + sizeof(T), 0); if (rhs) construct(*rhs); // Invoke copy constructor } ~LazyConstructor() { destroy(); } LazyConstructor& operator=(const LazyConstructor& rhs) { destroy(); if (rhs) construct(*rhs); // Invoke copy constructor return *this; } bool isConstructed() const { return ptr_ != NULL; } operator T*() const { return ptr_; } const T* operator->() const { ensureConstructed(); return ptr_; } T* operator->() { ensureConstructed(); return ptr_; } const T& operator*() const { ensureConstructed(); return *ptr_; } T& operator*() { ensureConstructed(); return *ptr_; } void destroy() { if (ptr_) ptr_->~T(); ptr_ = NULL; std::fill(data_, data_ + sizeof(T), 0); } void construct() { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(); } // MAX_ARGS = 6 // TEMPLATE = ''' // template <%s> // void construct(%s) // { // ensureNotConstructed(); // ptr_ = new (static_cast(data_)) T(%s); // }''' // for nargs in range(1, MAX_ARGS + 1): // nums = [(x + 1) for x in range(nargs)] // l1 = ['typename P%d' % x for x in nums] // l2 = ['typename ParamType::Type p%d' % (x, x) for x in nums] // l3 = ['p%d' % x for x in nums] // print(TEMPLATE % (', '.join(l1), ', '.join(l2), ', '.join(l3))) template void construct(typename ParamType::Type p1) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1); } template void construct(typename ParamType::Type p1, typename ParamType::Type p2) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1, p2); } template void construct(typename ParamType::Type p1, typename ParamType::Type p2, typename ParamType::Type p3) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1, p2, p3); } template void construct(typename ParamType::Type p1, typename ParamType::Type p2, typename ParamType::Type p3, typename ParamType::Type p4) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1, p2, p3, p4); } template void construct(typename ParamType::Type p1, typename ParamType::Type p2, typename ParamType::Type p3, typename ParamType::Type p4, typename ParamType::Type p5) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1, p2, p3, p4, p5); } template void construct(typename ParamType::Type p1, typename ParamType::Type p2, typename ParamType::Type p3, typename ParamType::Type p4, typename ParamType::Type p5, typename ParamType::Type p6) { ensureNotConstructed(); ptr_ = new (static_cast(data_)) T(p1, p2, p3, p4, p5, p6); } }; }