nested

template <typename T>
struct nested {
        T& value() &;
        const T& value() & const;
        T&& value() &&;
};

sol::nested<...> is a template class similar to sol::as_table, but with the caveat that every container type within the sol::nested type will be retrieved as a table from lua. This is helpful when you need to receive C++-style vectors, lists, and maps nested within each other: all of them will be deserialized from lua using table properties rather than anything else.

Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a C++ type. You can deserialize the Lua table into something explicitly using the sol::as_table_t marker for your get and conversion operations using sol. At that point, the returned type is deserialized from a table, meaning you cannot reference any kind of C++ data directly as you do with regular userdata/usertypes. All C++ type information is lost upon serialization into Lua.

The example provides a very in-depth look at both sol::as_table<T> and sol::nested<T>, and how the two are equivalent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

#include <vector>
#include <map>
#include "assert.hpp"
#include <iostream>


// nested allows serialization of maps with vectors inside, and vice-versa
// all from a nested structure of Lua tables
// it has less control over which pieces are considered tables in Lua,
// and which ones are considered userdata, but it covers a good 90% of cases
// where someone wants to handle a nested table
void demo(sol::nested<std::map<std::string, std::vector<std::string>>> src) {
	std::cout << "demo, sol::nested<...>" << std::endl;
	const auto& listmap = src.value();
	c_assert(listmap.size() == 2);
	for (const auto& kvp : listmap) {
		const std::vector<std::string>& strings = kvp.second;
		c_assert(strings.size() == 3);
		std::cout << "\t" << kvp.first << " = ";
		for (const auto& s : strings) {
			std::cout << "'" << s << "'" << " ";
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;
}

int main(int, char**) {
	std::cout << "=== containers retrieved from lua tables ===" << std::endl;
	
	sol::state lua;
	// bind the function
	lua.set_function("f", &demo);
	// Call it with a table that has string sequences set to distinct keys
	lua.script(R"(
t = { 
	key1 = {'hello', 'there', 'world'},
	key2 = {'bark', 'borf', 'woof'}
}
g(t)
	)");

	std::cout << std::endl;

	return 0;
}