Date: Mon, 25 May 2020 16:53:36 +0300
You are correct, this was my first implementation. I think "constexpr if"
is not very readable and I usually prefer tag dispatch.
About the arguments - yes, those are different types, but suppose the class
is passed from somewhere, here is my real code:
template<class PROTOCOL, class DB_ADAPTER, class CONNECTION>
> class KeyValueWorkerProcessor{
> // ...
> template<typename F>
> WorkerStatus do_accumulate_(F func){
> const auto &p = protocol_.getParams();
> if (p.size() != 4)
> return err_BadRequest_();
> const auto &key = p[1];
> uint16_t const count = from_string<uint16_t>(p[2]);
> const auto &prefix = p[3];
> protocol_.response_strings(buffer_, *class_invoke(db_, func, key,
> count, prefix)* );
> return WorkerStatus::WRITE;
> }
> auto do_getx(){
> return do_accumulate_(&DB_ADAPTER::getx);
> }
> auto do_count(){
> return do_accumulate_(&DB_ADAPTER::count);
> }
> auto do_sum(){
> return do_accumulate_(&DB_ADAPTER::sum);
> }
> auto do_min(){
> return do_accumulate_(&DB_ADAPTER::min);
> }
> auto do_max(){
> return do_accumulate_(&DB_ADAPTER::max);
> }
> // ...
> private:
> PROTOCOL &protocol_;
> DB_ADAPTER &db_;
> CONNECTION &buffer_;
> };
>
My first implementation had do_accumulate_() pasted 5 times - It was OK,
but very long and code duplication.
Second implementation was with lambdas. It was rather confusing and hard to
read.
Third implementation used direct code - "(db_.*func)(key, count,
prefix);", however I needed to remove "static" from my Mock adapter.
That was OK, but I thought - what if later I really need to call a static
method. Then I will need to do it as "normal" method and hope the optimizer
cleans up the code for me.
Current implementation works and looks very nice and clear, isn't it?
Nick
On Mon, May 25, 2020 at 3:37 PM Garrett May via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Are these not different types? One is a member function pointer, which
> requires two arguments - a Real* and an int - whereas the other is a
> function pointer which requires one argument - an int;
>
> You can do the following:
>
> template<typename C, typename F>
> auto user(C &c, F func){
> if constexpr(std::is_member_function_pointer<F>::value){
> return (c.*func)(5);
> } else{
> return func(5);
> }
> }
> And subsequently call via:
>
> *user(real, &Real::inc);*
>
> *user(real, Mock::inc);*
>
> On Mon, 25 May 2020, 1:16 pm Nikolay Mihaylov via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> Hello,
>>
>> suppose you have following clases:
>>
>> struct Mock{
>>> static int inc(int){
>>> return 0;
>>> } static int dec(int){
>>> return 0;
>>> }
>>> };struct Real{
>>> Real(int v) : v(v){} int inc(int a) const{
>>> return a + v;
>>> } int dec(int a) const{
>>> return a - v;
>>> }private:
>>> int v;
>>> };template<typename C, typename F>
>>> auto user(C &c, F func){
>>> return (c.*func)(5);
>>> }
>>
>> This will allow to call:
>>
>>
>> *user(real, &Real::inc);*
>> but will not allow to do
>>
>> *user(real, &Mock::inc);*
>>
>> However because of generic context, both calls must be possible.
>>
>> Here is simple implementation of the feature:
>>
>> #include <type_traits>
>>>
>>> namespace class_invoke_impl_{
>>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke_(T &&cl, F func, std::true_type,
>>> Args&&... args){
>>> return (std::forward<T>(cl).*func)(std::forward<Args>(args)...);
>>> }
>>
>>
>>
>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke_(T const &, F func, std::false_type,
>>> Args&&... args){
>>> return func(std::forward<Args>(args)...);
>>> }
>>> }
>>
>>
>>
>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke(T &&cl, F func, Args&&... args){
>>> using namespace class_invoke_impl_;
>>> return class_invoke_(std::forward<T>(cl), func,
>>> std::is_member_pointer<F>{}, std::forward<Args>(args)...);
>>> }
>>
>>
>>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
is not very readable and I usually prefer tag dispatch.
About the arguments - yes, those are different types, but suppose the class
is passed from somewhere, here is my real code:
template<class PROTOCOL, class DB_ADAPTER, class CONNECTION>
> class KeyValueWorkerProcessor{
> // ...
> template<typename F>
> WorkerStatus do_accumulate_(F func){
> const auto &p = protocol_.getParams();
> if (p.size() != 4)
> return err_BadRequest_();
> const auto &key = p[1];
> uint16_t const count = from_string<uint16_t>(p[2]);
> const auto &prefix = p[3];
> protocol_.response_strings(buffer_, *class_invoke(db_, func, key,
> count, prefix)* );
> return WorkerStatus::WRITE;
> }
> auto do_getx(){
> return do_accumulate_(&DB_ADAPTER::getx);
> }
> auto do_count(){
> return do_accumulate_(&DB_ADAPTER::count);
> }
> auto do_sum(){
> return do_accumulate_(&DB_ADAPTER::sum);
> }
> auto do_min(){
> return do_accumulate_(&DB_ADAPTER::min);
> }
> auto do_max(){
> return do_accumulate_(&DB_ADAPTER::max);
> }
> // ...
> private:
> PROTOCOL &protocol_;
> DB_ADAPTER &db_;
> CONNECTION &buffer_;
> };
>
My first implementation had do_accumulate_() pasted 5 times - It was OK,
but very long and code duplication.
Second implementation was with lambdas. It was rather confusing and hard to
read.
Third implementation used direct code - "(db_.*func)(key, count,
prefix);", however I needed to remove "static" from my Mock adapter.
That was OK, but I thought - what if later I really need to call a static
method. Then I will need to do it as "normal" method and hope the optimizer
cleans up the code for me.
Current implementation works and looks very nice and clear, isn't it?
Nick
On Mon, May 25, 2020 at 3:37 PM Garrett May via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Are these not different types? One is a member function pointer, which
> requires two arguments - a Real* and an int - whereas the other is a
> function pointer which requires one argument - an int;
>
> You can do the following:
>
> template<typename C, typename F>
> auto user(C &c, F func){
> if constexpr(std::is_member_function_pointer<F>::value){
> return (c.*func)(5);
> } else{
> return func(5);
> }
> }
> And subsequently call via:
>
> *user(real, &Real::inc);*
>
> *user(real, Mock::inc);*
>
> On Mon, 25 May 2020, 1:16 pm Nikolay Mihaylov via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> Hello,
>>
>> suppose you have following clases:
>>
>> struct Mock{
>>> static int inc(int){
>>> return 0;
>>> } static int dec(int){
>>> return 0;
>>> }
>>> };struct Real{
>>> Real(int v) : v(v){} int inc(int a) const{
>>> return a + v;
>>> } int dec(int a) const{
>>> return a - v;
>>> }private:
>>> int v;
>>> };template<typename C, typename F>
>>> auto user(C &c, F func){
>>> return (c.*func)(5);
>>> }
>>
>> This will allow to call:
>>
>>
>> *user(real, &Real::inc);*
>> but will not allow to do
>>
>> *user(real, &Mock::inc);*
>>
>> However because of generic context, both calls must be possible.
>>
>> Here is simple implementation of the feature:
>>
>> #include <type_traits>
>>>
>>> namespace class_invoke_impl_{
>>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke_(T &&cl, F func, std::true_type,
>>> Args&&... args){
>>> return (std::forward<T>(cl).*func)(std::forward<Args>(args)...);
>>> }
>>
>>
>>
>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke_(T const &, F func, std::false_type,
>>> Args&&... args){
>>> return func(std::forward<Args>(args)...);
>>> }
>>> }
>>
>>
>>
>> template <class T, class F, class... Args>
>>> constexpr auto class_invoke(T &&cl, F func, Args&&... args){
>>> using namespace class_invoke_impl_;
>>> return class_invoke_(std::forward<T>(cl), func,
>>> std::is_member_pointer<F>{}, std::forward<Args>(args)...);
>>> }
>>
>>
>>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2020-05-25 08:57:18