variadic class template datastructure: implement key-value anc iteration

Hi.

I recently found a post about variadic data structure and I got the idea to test it on a structure to do a struct or class that know his members.

The goal will to use the data in it as usual class, but the will have function implemented in inheritance to stringify and parse to JSON, for example.

Now, I’m able, like in the example, to access the data via the variadic list with template index, but I can only do this outside the definition of the class. Because of that, and because they are class template, I’ve been unable to find a way to access the elements via key string or make an ‘forEach()’ function…

template <typename T>
class InterfaceObj {
public:
	InterfaceObj(T& val, const char* key) : value(val), _key(key) {  };
	const char* _key;
	T& value;
	InterfaceObj<T> operator=(T _value) { value = _value; };
	T& operator()(){ return value;};
	char* getKey() const { return _key; };
};

template <typename T, size_t S>
struct Array {
	Array() : _size(S) { array = new T[_size];};
	~Array() { delete[] array; array = NULL; };
	T* array;
	T& operator[](size_t x) { return array[x]; }
	size_t size() { return _size; };
private:
	const size_t _size;
};

namespace InterfaceHelper {
	template<size_t idx, typename T>
	struct GetHelper;

	template<typename T, typename ... Rest>
	struct GetByKey;

	template<typename T>
	static size_t strcmpHelper(char* key, size_t idx, InterfaceObj<T> obj) { return strcmp(key, obj.getKey()) == 0 ? 0 : idx-1; }
};

template<typename ... T>
struct Interface
{
};

template<typename T, typename ... Rest>
struct Interface<T, Rest ...>
{
    Interface(const InterfaceObj<T> first, const InterfaceObj<Rest> ... rest)
        : first(first)		
        , rest(rest...)  
    {}
    
    InterfaceObj<T> first;	
    Interface<Rest ... > rest; 
    static size_t size() {return sizeof(rest)/sizeof(first)+1;};
        
   template<size_t idx>
   auto get() -> decltype(InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this))
    {
        return InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this);
    }
    
};

template<typename T, typename ... Rest>
struct InterfaceHelper::GetHelper<0, Interface<T, Rest ... >> {
    static InterfaceObj<T>& get(Interface<T, Rest...>& data)
    {
        return data.first;
    }

};


template<size_t idx, typename T, typename ... Rest>
struct InterfaceHelper::GetHelper<idx, Interface<T, Rest ... >> {
    static auto get(Interface<T, Rest...>& data) -> decltype(GetHelper<idx-1, Interface<Rest ...>>::get(data.rest))
    {
        return GetHelper<idx-1, Interface<Rest ...>>::get(data.rest);
    }
};

//usage example
struct MyData : public Interface<int, float, char*, Array<double, 10>> {
	MyData() : Interface(
		InterfaceObj<int>(key0, "key0"),
		InterfaceObj<float>(key1, "key1"),
		InterfaceObj<char*>(key2, "key2"),
		InterfaceObj<Array<double, 10>>(key3, "Key3")
		) {};

	int key0;
	float key1;
	char* key2;
	Array<double, 10> key3;
};

struct MainData : public Interface<int, byte, MyData> {
	MainData() : Interface(
		InterfaceObj<int>(mainDataInt, "mainDataInt"),
		InterfaceObj<byte>(mainDataByte, "mainDataByte"),
		InterfaceObj<MyData>(childData, "childData")
		) {};
	int mainDataInt = 224;
	byte mainDataByte = 2;
	MyData childData;
};

MainData data;

void setup(){ 



void loop(){}

I would like, at first, be able to make an iteration, so it will be easier, in the future to make a stringify and parse function, and an overload of operator… so make a function get(char* key).

Each time I hurt my face by something that have to be know at compile time…

and auto keyword, on arduino, because it need trailing, is not easy to implement…

also, I’ve read about hash table, that’s not what I want to do exactly, but the is may something similar to do with a kay that is faster than strcmp()…

What exactly do you need variadic template data structures for? Parsing a string into the data structure, or serializing the data structure to json will require you to specialize the template anyway.

nitrof: also, I've read about hash table, that's not what I want to do exactly, but the is may something similar to do with a kay that is faster than strcmp()...

Why do you want to index by a string key in the first place? Depending on the number of variadic arguments, the hash-function will take longer to compute the hash than you walking through the array by numeric index.

the ultimate goal is to make an interface that have the easiest use of in interface in typescript...

you just define you structure data, then you could just export it to JSON... by overload or by passing JSON object...

after.. I what to be able to easily parse JSON and/or use the object as JSON object:

myObject["someKey"] = 5

nitrof: the ultimate goal is to make an interface that have the easiest use of in interface in typescript...

That does not make any sense.

nitrof: you just define you structure data, then you could just export it to JSON... by overload or by passing JSON object...

after.. I what to be able to easily parse JSON and/or use the object as JSON object:

myObject["someKey"] = 5

How is it different than the existing library?