问题
Well, my colleague is pretty in depth nitpicking about eliminating unnecessarily code instantiations for destructor functions. Still same situation, as mentioned in this question:
- Very limited space for
.text
section (less 256 KB) - Code base should scale among several targets, including the most limited ones
- Well known use cases of the code base by means some destructor logic is neccesary to manage object lifetimes or not (for many cases life-time of objects is infinite, unless the hardware is reset)
We have a target, that's very limited by means of .text
section space available.
Unfortunately the GCC compiler will apparently instantiate code for even non virtual destructors, that actually have no side effects.
To get rid of these instantiatons he came up with the following wrapper construct, to eliminate the useless destructor calls:
The wrapper class:
#include <iostream>
#include <cstdint>
#include <utility>
template <typename T>
struct noop_destructor {
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
template<typename... Args>
noop_destructor(Args&&... args) {
new (reinterpret_cast<void*>(wrapped_data)) T(std::forward<Args>(args)...);
}
explicit noop_destructor(const noop_destructor& rhs) {
std::copy(rhs.wrapped_data,rhs.wrapped_data+sizeof(T),wrapped_data);
}
noop_destructor& operator=(const noop_destructor& rhs) {
std::copy(rhs.wrapped_data,rhs.wrapped_data+sizeof(T),wrapped_data);
return *this;
}
pointer operator->() {
return reinterpret_cast<pointer>(wrapped_data);
}
const_pointer operator->() const {
return reinterpret_cast<const_pointer>(wrapped_data);
}
reference operator*() {
return *reinterpret_cast<pointer>(wrapped_data);
}
const_reference operator*() const {
return *reinterpret_cast<const_pointer>(wrapped_data);
}
private:
uint8_t wrapped_data[sizeof(T)] __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));
};
A wrapped class (just ignore the side effect of calling std::cout << ...
in the destructor, the real life classes in question to be wrapped, have just empty, non virtual destructors)
class A {
public:
A() : x_() {}
A(int x) : x_(x) {}
~A() {
std::cout << "noop destructor call of class A" << std::endl;
}
void foo() {
std::cout << "x_ = " << x_ << std::endl;
}
private:
int x_;
};
Some instantiations to demonstrate behavior:
int main() {
A a1(5);
noop_destructor<A> a2;
a1.foo();
(*a2).foo();
return 0;
}
The approach just works fine (as you can see from the above code sample).
What I actually don't like about it, is you have no proof if a class actually can be wrapped with noop_destructor<>
, and there's no indicator if T
's destructor is actually empty, and can be safely eliminated or not.
Does anyone have an idea, how to make this more safe from a semantical level?
来源:https://stackoverflow.com/questions/28909598/eliminating-instantiation-of-useless-destructor-calls