$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] sqlpp11, 3rd iteration
From: Adam Wulkiewicz (adam.wulkiewicz_at_[hidden])
Date: 2014-08-19 18:34:15
Roland Bock wrote:
> On 2014-08-19 18:56, Adam Wulkiewicz wrote:
>> Ok AFAIU a struct like _member_t should define some convenient member
>> variable for the user and must define operator() for the library.
>> But the rest could be automatically generated, couldn't it?
>> Why not just pass a list of templates of classes adapted to MemberType
>> concept (defined operator()) into the table/column/etc.?
>> I'm thinking about something like the code below. I don't know exactly
>> what's required so this is just an example of a technique rather than
>> a solution ready-to-use in sqlpp.
> The idea is good. For the columns, you will have to add a few more
> parameters, e.g. the value_type (mandatory), can_be_null,
> must_not_insert, must_not_update, null_is_trivial, trivial_is_null,
> maybe as per your suggestion a default value or a function for producing
> it. That default stuff might be tough in such a design.
The additional traits would be a list of variadic template parameters.
So if this list contained only one type, e.g. sqlpp::default_traits the
default traits could be generated e.g. by specializing sqlpp::make_traits<>.
Since it's impossible to define a default argument of a template
parameters pack (another missing language feature?) it could be
"simulated" with something like:
template <template <typename> class Name,
typename Trait0 = default_traits,
typename... Traits
>
struct column
{
using traits = make_traits<Trait0, Traits...>;
};
Or all traits could be passed as one list type like MPL sequence or
someting like that as you wrote below.
> But thats manageable. And yes, the code would be shorter, although not
> that much, I suspect. The only problem I have with it is that now the
> column types are going to be about a hundred characters long. And users
> are going to operate on columns all the time. So error message have to
> be short.
Do you have in mind the code of the library or user's code?
I expect that the user's code, even not using defaults, would be a lot
shorter.
But the most important is that the definition of a table would probably
be more clear, in one place, etc.
Or am I wrong?
>
> I would thus add a struct which inherits from the column template
> instance for each column, e..g.
>
> struct alpha: public column<tab_member, alpha_member, sqlpp::integral,
> sqlpp::tag::must_not_insert, ...> {};
With variadic templates the construction of traits out of this would be
straightforward.
An alternative would be to take additional parameters/traits list as the
3rd parameter as you wrote below.
Btw, why a column must be aware about a Table?
Can a table also have some traits specified?
I'm asking because then there would be 2 lists that should be passed -
Members and Traits.
> I tried something similar a while back but failed, which is mainly due
> to lack of perseverance, I guess.
>
> Right now, I am happy with the current design because it is quite easy
> to change things, like introducing that default value or a function for
> handling attempts to read NULL.
Sure, I'm not saying that you should change the design. I'm just sharing
my thoughts.
> If you want to put everything into that one list of template parameters,
> it is much tougher, IMO. I mean how would you add a function for
> handling access to NULL value? You would need another class, I think.
> And you would have to group those tags into a tuple or type_set, because
> otherwise it would be ugly to add another optional parameter...
I'm guessing that the function or ... could be passed as yet another
trait like:
struct alpha: public column<tab_member, alpha_member, sqlpp::trivial_value<some_generator> >
If not passed, a default trivial value would be used.
The best would be to somehow pass a static value in compile-time but
only integral types could be handled this way. The reference to the
global external variable of non-integral type could also be passed as a
template parameter but still it would have to be defined somewhere so it
wouldn't be convenient.
So some_generator could be a type of default-constructible function
object or a pointer to function, etc.
Or do someone knows some trick that could be used here?
Regards,
Adam