20 Aug
2014
20 Aug
'14
6:21 p.m.
On 2014-08-20 19:21, Adam Wulkiewicz wrote: > Roland Bock wrote: >> On 2014-08-20 00:34, Adam Wulkiewicz wrote: >>> Roland Bock wrote: >>>> 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? >> User's code: >> >> * You have the member template which must be defined outside. >> * You have the get_name method which should be defined outside the >> member template since I have no instance of that template where I >> need the name (you still cant use a string literal as template >> parameter directly, right? Like table_t<"sample">?) >> * You need to group the member template and the get_name method since >> they are always used in combination >> * You need a struct or class to hold the default value or function >> >> And if you don't want to have all this flying around as individual >> pieces with individual names, then you will group it into a class. And >> you're back to where you started. > Yes, passing a string literal isn't possible unfortunately. > > So the member and a name must be bound together somehow but the rest > could still be automatically generated. In particular, IMHO the > specification of a default value should be optional (e.g. passed as > yet another trait). The library shouldn't require defining it each > time, even as some dummy function if a user wanted to use exceptions. > Besides, defining the default value generator as external to the > member-"name" binding would probably be preferable because the same > generator could be reused for many columns. However I don't expect > that the generator would do something complicated, rather just return > a value. But for integral members it could be predefined in the sqlpp > and it could be passed as just 1 additional type. Right. > >> >>> 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 think you're wrong, although I'd love to be wrong about that :-) [...] > Hmm, is the member template used in many places? AFAIU it must be used > at least 2 times, to define columns, tables, etc. and later to > construct a row. - Tables, - subqueries used as tables (basically tables again), - result rows - parameter sets for prepared queries > Well, it isn't that important. :-) > > If you write it this way: > > struct Alpha > { > static constexpr const char* _get_name() { return "alpha"; } > template<typename T> > struct _member_t > { > T alpha; > T& operator()() { return alpha; } > const T& operator()() const { return alpha; } > }; > }; > > struct alpha: public column_t<MyTable, Alpha, > sqlpp::make_traits<sqlpp::integral, > sqlpp::trivial_integral<42>, ...>>; > > it's shorter :) > > The above assuming that sqlpp::trivial_integral<> is a > default-constructible functor returning a value convertible to > int64_t. So basically trivial_t but with operator() instead of > get_trivial_value(). Nice! I like it :-) I will definitely experiment with that as soon as I find the time (probably after CppCon). > > <snip> > > It could be convenient to generate a type of a non-parameter lambda > expression in unevaluated context, something like: > > sqlpp::make_traits<sqlpp::trivial_value<decltype([](){return 0;})>> > > > but this is not possible too. Yeah, tried that too :-) Cheers, Roland