#include <iostream>
#include <vector>
#include <memory>
using namespace std;

template<typename T>
struct ObjectPointers {
    const std::shared_ptr<ObjectPointers<T>> left;
    const std::shared_ptr<ObjectPointers<T>> right;
    std::vector<T> data;

    // initialize left and right in constructor
    ObjectPointers(std::initializer_list<T> list) : data(list) {
    }

    ObjectPointers(const ObjectPointers &c) = default;
    ~ObjectPointers(){  // no need,  shared ptr take care
     }

    ObjectPointers(std::shared_ptr<ObjectPointers<T>> left, std::shared_ptr<ObjectPointers<T>> right) : left(left), right(right) {}

	void show()const {
		std::cout<<"data\n";
		for (auto &x:data) 
			std::cout<<"\t"<<x<<std::endl; 
		std::cout<<"end of data\n";
		if (left) {
		    std::cout<<"Recurstive left:\n";
			left->show();
		    std::cout<<"end of recursive left\n";
		}
		else cout<<"no left\n"; 
		if (right){
			std::cout<<"Recurstive right:\n";
			right->show(); 
			std::cout<<"end of recursive right\n";
		}
		else cout<<"no right\n"; 
	}
};

//overload +
template <class T>
ObjectPointers<T> operator+ (ObjectPointers<T> a, ObjectPointers<T> b)  {
     // I create a new object with the left and right of the current object
     return ObjectPointers<T>(std::make_shared<ObjectPointers<T>>(a), std::make_shared<ObjectPointers<T>>(b));
}


int main() {
    ObjectPointers<int> a = {1, 2, 3};
    ObjectPointers<int> b = {4, 5, 6};
    ObjectPointers<int> c = a + b;
    c.show(); 

    return 0;
}