Note that idreflexpr takes a compile time string, it does not necessarily have to be taken from a reflection meta object. The examples below use both, names from meta objects and names from other compile time strings.
*) sqlpp11:
In this EDSL for SQL in C++, tables are represented by types that have one or more data members representing the columns.
You can then create SQL and evaluate statements like this:
for (const auto& row : db(select(tab.id, tab.first_name, tab.last_name)
.from(tab)
.where(tab.dob > 1920)))
{
foo(row.id, row.first_name, row.last_name);
}
The type of row is constructed by the library depending of the selected columns. This works today. So why bother? Because it is annoying to code. For each name, there has to be a separate template that happens to have a member of that name and can then be used as a base class. It involves code generators, macros, or someone who likes repetitive typing a lot.
As mentioned by Matus, the long term goal is to have something like this:
Then neither tables not rows would require any inheritance any more. In the case of tables, it currently is variadic CRTP. The name would just be template parameter for the column or result field types.
Assuming that compile time strings could be created from string literals, we could also have
for (const auto& row : db(select(tabFoo.id.as<"left"_ct>(),
tabBar.id.as<"right"_ct>())
.from(tabFoo.join(tabBar).on(tabFoo.name == tabBar.name))
.where(tabFoo.id < 1000)))
{
doSomething(row.left, row.right);
}
As of now, such names as left and right need to be template classes again, generated by a PP macro outside of the current function (aka far away).
*) sqlpp11 for containers:
Eric Niebler once said that he would like to see SQL for containers or streams, too. Well, actually I have a prototype for that, but if I want to run SQL on say a vector<Foo>, then I need create a class that acts as a table definition with columns that represent the data members of Foo. As of today I see no other way than to use a code generator. That is a lot of overhead. Nobody would use that.
With the current reflection plus idreflexpr I could generate those table-classes with a little bit of generic meta programming directly from Foo. Suddenly, this is no hassle at all for the library user.
I would probably use that every now and then. Sometimes SQL expressions might be simpler to read and write than STL algorithms with a bunch of lambdas.
*) Named tuple data members:
Say you want to return several values from a function. Tuple or hand-coded struct?
- Tuples are so much easier for the author of the function. But they are ugly for users who want to access certain values.
- Hand-written structs might need additional comparison operators. And they aren't well suited for generic programming sometimes.
So how about we had a tuple, whose data members were defined by type AND name? You wouldn't have to choose any more. You could access data members by name like in a "normal" struct or by index as in today's tuple.
Cheers,
Roland