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)63 void addToCaptures(const ICapture* ptr) { captures.push_back(ptr); }
64 
popFromCaptures()65 void popFromCaptures() { captures.pop_back(); }
66 
printCaptures()67 void 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()74 int 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