-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add pass-by-reference option for operator>>
#60
Comments
operator>>
This seems to be the exact use-case for which reference-wrappers were designed. Would you consider that an option? Basically, your
Note that |
From the example in the docs on When I tried using include/modern_sqlite/utility/function_traits.h:12:13:
error: reference to overloaded function could not be resolved; did you mean to call it?
decltype(&Function::operator())
^~~~~~~~~~~~~~~~~~~~~ which confuses me, because there are no obvious (to me) overloads of That said, is there any advantage to using a pass-by-value signature and not implementing the pass-by-reference method? My thoughts on the matter:
|
I see the point you are trying to make, and its a valid point. I'm trying to come up with better example where we would need that additional template but all i can think of would be solved by adding proper code or trivial in terms of performance loss. Or and that's very possible i totally miss the point of this ;) |
@faultyserver Thanks for the detailed explanation. @bjoernpollex @Killili |
@Killili I also removed the extensions folder, since the type system is not working and those are extra files. |
@aminroosta Wonderful! Your implementation certainly looks cleaner than mine. I was unaware of Universal References. @Killili I think you were mostly on point, and a proper Singleton definitely would've solved the immediate issue as well. Thanks for the suggestion. PS: Thanks for this line. return std::move(person_builder.results); // move to avoid copying data ;-) |
While trying to make good use of the lambda syntax for pulling out results from a query, I hit an issue where the function is being passed by value (and thus copied), causing my results to get lost when the operator exited and the variable went out of scope.
In short, I want to create class instances for each result row, but also want to avoid code repetition. I currently have something similar to this:
The relevant code for this issue is in
Route::all()
at the end of the code block above, with the expression>> route_builder
. I am passing an instance of theBuilder
class, which implementsoperator()
(as required byutility::function_traits
), and is thus runnable by the>>
implementation.However, the current implementation takes the argument by value, meaning a local copy of the instance is created for use in the function, and any side effects are discarded when that variable falls out of scope (when
operator>>
returns).In other words,
route_builder.results
- which I would expect to contain theRoute
instances of each row returned from the query - is actually empty, because the operations were performed on an ephemeral copy of the instance.My solution to this was to modify the
Function
specialization ofoperator>>
to take its parameter by reference:However, this does not work with the original, intended behavior of using a temporary lambda as the argument:
To get around this, a new specialization that takes an rvalue reference for these temporaries can be introduced. The resulting changes to the header would look like this:
This works because lvalues will prefer matching to the lvalue reference specialization (the first one), and rvalue temporaries will prefer matching to the rvalue reference specialization.
I have tested this implementation with classes defining
operator()
and direct lambdas, and both are working as of now. That said, though, I do not consider myself an expert in C++, so I'm not sure if this is a feasible solution.The text was updated successfully, but these errors were encountered: