How to explicitly cast argument to match an expected function parameter?









up vote
0
down vote

favorite












I am trying to write a generic function to compute an average over a certain range.



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

if (numElements > 0)
sum /= numElements;
return sum;



The problam I am having is with the usage of the /= operator, but to better clarify the arguments of this function, let me clarify them:




  • Range range is any object that defines a range through begin() and end() member funcitons. I may need to add const& to avoid unnecessary copying.


  • Ret zero defines the neutral element of the addition used when computing the average. It could be just a scalar, but will work with vectors or matrices too for example.


  • Func extract is a function (usually given as a lambda function) that converts the elements of the range into Ret values that I average over. In practice I use it as a getter of a specific field in big objects that I iterate over.



    I could probably define it as std::function<Ret(decltype(*range.begin()))> or something similar, if C++ didn't have problems deducting types this way.



I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically.



In my use case, for example, Ret works with float-s and this gives me an annoying warning:



warning: 'argument': conversion from 'int' to 'float', possible loss of data



So, what are my options to make the above function clean and work with any suitable operator/=?




I tried, for example, to deduct the type of the right argument of the operator and explicitly cast to it:



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

using F = std::remove_pointer<decltype(&Ret::operator/=)>;

if (numElements > 0)
sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
return sum;



But I get a lot of compile errors, suggesting that I don't know what I am doing. Starts with:



error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined


That's probably because boost::function_traits does not work with member functions, just regular ones?



I am also concerned that this solution may not work when:



  • The operator/= is not given as a member function, but as a regular function with two arguments.

  • The operator/= is overloaded with respect to its right operand. An int may match only one of the overloads - so there is no ambiguity, but decltype won't know which overload to take.

  • I would prefer not to use boost but stick to the powers provided by newest C++ standards









share|improve this question

















  • 1




    Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
    – WhiZTiM
    2 days ago











  • Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
    – CygnusX1
    2 days ago











  • "I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
    – max66
    2 days ago










  • It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
    – CygnusX1
    2 days ago










  • It would improve the question to post a MCVE showing an example of the undesirable case
    – M.M
    yesterday















up vote
0
down vote

favorite












I am trying to write a generic function to compute an average over a certain range.



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

if (numElements > 0)
sum /= numElements;
return sum;



The problam I am having is with the usage of the /= operator, but to better clarify the arguments of this function, let me clarify them:




  • Range range is any object that defines a range through begin() and end() member funcitons. I may need to add const& to avoid unnecessary copying.


  • Ret zero defines the neutral element of the addition used when computing the average. It could be just a scalar, but will work with vectors or matrices too for example.


  • Func extract is a function (usually given as a lambda function) that converts the elements of the range into Ret values that I average over. In practice I use it as a getter of a specific field in big objects that I iterate over.



    I could probably define it as std::function<Ret(decltype(*range.begin()))> or something similar, if C++ didn't have problems deducting types this way.



I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically.



In my use case, for example, Ret works with float-s and this gives me an annoying warning:



warning: 'argument': conversion from 'int' to 'float', possible loss of data



So, what are my options to make the above function clean and work with any suitable operator/=?




I tried, for example, to deduct the type of the right argument of the operator and explicitly cast to it:



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

using F = std::remove_pointer<decltype(&Ret::operator/=)>;

if (numElements > 0)
sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
return sum;



But I get a lot of compile errors, suggesting that I don't know what I am doing. Starts with:



error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined


That's probably because boost::function_traits does not work with member functions, just regular ones?



I am also concerned that this solution may not work when:



  • The operator/= is not given as a member function, but as a regular function with two arguments.

  • The operator/= is overloaded with respect to its right operand. An int may match only one of the overloads - so there is no ambiguity, but decltype won't know which overload to take.

  • I would prefer not to use boost but stick to the powers provided by newest C++ standards









share|improve this question

















  • 1




    Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
    – WhiZTiM
    2 days ago











  • Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
    – CygnusX1
    2 days ago











  • "I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
    – max66
    2 days ago










  • It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
    – CygnusX1
    2 days ago










  • It would improve the question to post a MCVE showing an example of the undesirable case
    – M.M
    yesterday













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I am trying to write a generic function to compute an average over a certain range.



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

if (numElements > 0)
sum /= numElements;
return sum;



The problam I am having is with the usage of the /= operator, but to better clarify the arguments of this function, let me clarify them:




  • Range range is any object that defines a range through begin() and end() member funcitons. I may need to add const& to avoid unnecessary copying.


  • Ret zero defines the neutral element of the addition used when computing the average. It could be just a scalar, but will work with vectors or matrices too for example.


  • Func extract is a function (usually given as a lambda function) that converts the elements of the range into Ret values that I average over. In practice I use it as a getter of a specific field in big objects that I iterate over.



    I could probably define it as std::function<Ret(decltype(*range.begin()))> or something similar, if C++ didn't have problems deducting types this way.



I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically.



In my use case, for example, Ret works with float-s and this gives me an annoying warning:



warning: 'argument': conversion from 'int' to 'float', possible loss of data



So, what are my options to make the above function clean and work with any suitable operator/=?




I tried, for example, to deduct the type of the right argument of the operator and explicitly cast to it:



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

using F = std::remove_pointer<decltype(&Ret::operator/=)>;

if (numElements > 0)
sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
return sum;



But I get a lot of compile errors, suggesting that I don't know what I am doing. Starts with:



error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined


That's probably because boost::function_traits does not work with member functions, just regular ones?



I am also concerned that this solution may not work when:



  • The operator/= is not given as a member function, but as a regular function with two arguments.

  • The operator/= is overloaded with respect to its right operand. An int may match only one of the overloads - so there is no ambiguity, but decltype won't know which overload to take.

  • I would prefer not to use boost but stick to the powers provided by newest C++ standards









share|improve this question













I am trying to write a generic function to compute an average over a certain range.



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

if (numElements > 0)
sum /= numElements;
return sum;



The problam I am having is with the usage of the /= operator, but to better clarify the arguments of this function, let me clarify them:




  • Range range is any object that defines a range through begin() and end() member funcitons. I may need to add const& to avoid unnecessary copying.


  • Ret zero defines the neutral element of the addition used when computing the average. It could be just a scalar, but will work with vectors or matrices too for example.


  • Func extract is a function (usually given as a lambda function) that converts the elements of the range into Ret values that I average over. In practice I use it as a getter of a specific field in big objects that I iterate over.



    I could probably define it as std::function<Ret(decltype(*range.begin()))> or something similar, if C++ didn't have problems deducting types this way.



I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically.



In my use case, for example, Ret works with float-s and this gives me an annoying warning:



warning: 'argument': conversion from 'int' to 'float', possible loss of data



So, what are my options to make the above function clean and work with any suitable operator/=?




I tried, for example, to deduct the type of the right argument of the operator and explicitly cast to it:



template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract)
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range)
sum += extract(elem);
++numElements;

using F = std::remove_pointer<decltype(&Ret::operator/=)>;

if (numElements > 0)
sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
return sum;



But I get a lot of compile errors, suggesting that I don't know what I am doing. Starts with:



error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined


That's probably because boost::function_traits does not work with member functions, just regular ones?



I am also concerned that this solution may not work when:



  • The operator/= is not given as a member function, but as a regular function with two arguments.

  • The operator/= is overloaded with respect to its right operand. An int may match only one of the overloads - so there is no ambiguity, but decltype won't know which overload to take.

  • I would prefer not to use boost but stick to the powers provided by newest C++ standards






c++ c++11 c++14 c++17 typetraits






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 2 days ago









CygnusX1

14.6k34080




14.6k34080







  • 1




    Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
    – WhiZTiM
    2 days ago











  • Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
    – CygnusX1
    2 days ago











  • "I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
    – max66
    2 days ago










  • It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
    – CygnusX1
    2 days ago










  • It would improve the question to post a MCVE showing an example of the undesirable case
    – M.M
    yesterday













  • 1




    Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
    – WhiZTiM
    2 days ago











  • Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
    – CygnusX1
    2 days ago











  • "I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
    – max66
    2 days ago










  • It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
    – CygnusX1
    2 days ago










  • It would improve the question to post a MCVE showing an example of the undesirable case
    – M.M
    yesterday








1




1




Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago





Having to deduce either the argument type or return type of Arithmetic or Compound operators is almost always a sign of bad API or some misuse; operator overloading and its uses are to make simple things simple and clear. Doing some deductions at its point-of-use is doesn't smell good; That said, you can delegate the line sum /= ... to a utility class-template that treats certain categories of types separately; You can templatize on float to treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago













Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
– CygnusX1
2 days ago





Is the above average function a design flaw or a misuse? Because I doubt that a Float class (used as Ret) encapsulating a built-in float would have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with any Ret.
– CygnusX1
2 days ago













"I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
– max66
2 days ago




"I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically." - but you can accept to test a limited list of potential types for divisor? I mean: is good for you if the divisor is int, or long, or..., or float or double, or long double or nothing else?
– max66
2 days ago












It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
– CygnusX1
2 days ago




It could be anything. Maybe a BigNum class? Or a rational type? I do not expect the number of elements to exceed int ever, but the operators provided by Ret may operate on any type that int is convertible to.
– CygnusX1
2 days ago












It would improve the question to post a MCVE showing an example of the undesirable case
– M.M
yesterday





It would improve the question to post a MCVE showing an example of the undesirable case
– M.M
yesterday













1 Answer
1






active

oldest

votes

















up vote
0
down vote













You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.






share|improve this answer




















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237912%2fhow-to-explicitly-cast-argument-to-match-an-expected-function-parameter%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.






    share|improve this answer
























      up vote
      0
      down vote













      You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.






      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.






        share|improve this answer












        You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        Aganju

        4,9891621




        4,9891621



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237912%2fhow-to-explicitly-cast-argument-to-match-an-expected-function-parameter%23new-answer', 'question_page');

            );

            Post as a guest














































































            這個網誌中的熱門文章

            Barbados

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3