1 #include <vector> 2 #include <utility> 3 #include <iostream> 4 #include <string> 5 #include <list> 6 #include <new> 7 8 #define CAT_IMPL(s1, s2) s1##s2 9 #define CAT(s1, s2) CAT_IMPL(s1, s2) 10 #define ANONYMOUS(x) CAT(x, __COUNTER__) 11 12 #define NUM_CAPTURES_ON_STACK 5 13 14 struct ICapture { virtual std::string toString() const = 0; }; 15 16 void addToCaptures(const ICapture* ptr); 17 void popFromCaptures(); 18 void printCaptures(); 19 20 struct InfoBuilder { 21 template<typename T> 22 struct Capture : ICapture { 23 const T* capture; 24 CaptureInfoBuilder::Capture25 Capture(const T* in) : capture(in) {} toStringInfoBuilder::Capture26 std::string toString() const override { return std::to_string(*capture); } 27 }; 28 29 struct Chunk { char buf[sizeof(Capture<char>)]; }; 30 31 Chunk stackChunks[NUM_CAPTURES_ON_STACK]; 32 int numCaptures = 0; 33 std::list<Chunk> heapChunks; 34 35 template<typename T> operator <<InfoBuilder36 InfoBuilder& operator<<(const T& in) { 37 if(numCaptures < NUM_CAPTURES_ON_STACK) { 38 addToCaptures(new (stackChunks[numCaptures].buf) Capture<T>(&in)); 39 } else { 40 heapChunks.push_back(Chunk()); 41 addToCaptures(new (heapChunks.back().buf) Capture<T>(&in)); 42 } 43 ++numCaptures; 44 return *this; 45 } 46 ~InfoBuilderInfoBuilder47 ~InfoBuilder() { 48 for(int i = 0; i < numCaptures; ++i) 49 popFromCaptures(); 50 } 51 52 template<typename T> 53 InfoBuilder& operator<<(const T&&) = delete; // prevent rvalues from being captured 54 }; 55 56 #define INFO_IMPL(name, x) InfoBuilder name; name << x 57 #define INFO(x) INFO_IMPL(ANONYMOUS(_CAPTURE_), x) 58 59 // impl 60 61 std::vector<const ICapture*> captures; 62 addToCaptures(const ICapture * ptr)63void addToCaptures(const ICapture* ptr) { captures.push_back(ptr); } 64 popFromCaptures()65void popFromCaptures() { captures.pop_back(); } 66 printCaptures()67void printCaptures() { 68 for(size_t i = 0; i < captures.size(); ++i) 69 std::cout << captures[i]->toString() << std::endl; 70 } 71 72 // usage 73 main()74int main() { 75 int var1 = 42; 76 int var2 = 43; 77 int var3 = 45; 78 int var4 = 46; 79 int var5 = 47; 80 float var6 = 48.f; 81 bool var7 = true; 82 83 INFO(var1 << var2 << var3 << var4 << var5 << var6 << var7); 84 85 printCaptures(); 86 } 87