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 rangeis any object that defines a range throughbegin()andend()member funcitons. I may need to addconst&to avoid unnecessary copying.Ret zerodefines 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 extractis a function (usually given as a lambda function) that converts the elements of the range intoRetvalues 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. Anintmay match only one of the overloads - so there is no ambiguity, butdecltypewon't know which overload to take. - I would prefer not to use
boostbut stick to the powers provided by newest C++ standards
c++ c++11 c++14 c++17 typetraits
add a comment |
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 rangeis any object that defines a range throughbegin()andend()member funcitons. I may need to addconst&to avoid unnecessary copying.Ret zerodefines 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 extractis a function (usually given as a lambda function) that converts the elements of the range intoRetvalues 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. Anintmay match only one of the overloads - so there is no ambiguity, butdecltypewon't know which overload to take. - I would prefer not to use
boostbut stick to the powers provided by newest C++ standards
c++ c++11 c++14 c++17 typetraits
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 linesum /= ...to a utilityclass-templatethat treats certain categories of types separately; You can templatize onfloatto treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaveragefunction a design flaw or a misuse? Because I doubt that aFloatclass (used asRet) encapsulating a built-infloatwould have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with anyRet.
– 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 isint, orlong, or..., orfloatordouble, orlong doubleor nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNumclass? Or a rational type? I do not expect the number of elements to exceedintever, but the operators provided byRetmay operate on any type thatintis 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
add a comment |
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 rangeis any object that defines a range throughbegin()andend()member funcitons. I may need to addconst&to avoid unnecessary copying.Ret zerodefines 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 extractis a function (usually given as a lambda function) that converts the elements of the range intoRetvalues 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. Anintmay match only one of the overloads - so there is no ambiguity, butdecltypewon't know which overload to take. - I would prefer not to use
boostbut stick to the powers provided by newest C++ standards
c++ c++11 c++14 c++17 typetraits
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 rangeis any object that defines a range throughbegin()andend()member funcitons. I may need to addconst&to avoid unnecessary copying.Ret zerodefines 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 extractis a function (usually given as a lambda function) that converts the elements of the range intoRetvalues 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. Anintmay match only one of the overloads - so there is no ambiguity, butdecltypewon't know which overload to take. - I would prefer not to use
boostbut stick to the powers provided by newest C++ standards
c++ c++11 c++14 c++17 typetraits
c++ c++11 c++14 c++17 typetraits
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 linesum /= ...to a utilityclass-templatethat treats certain categories of types separately; You can templatize onfloatto treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaveragefunction a design flaw or a misuse? Because I doubt that aFloatclass (used asRet) encapsulating a built-infloatwould have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with anyRet.
– 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 isint, orlong, or..., orfloatordouble, orlong doubleor nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNumclass? Or a rational type? I do not expect the number of elements to exceedintever, but the operators provided byRetmay operate on any type thatintis 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
add a comment |
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 linesum /= ...to a utilityclass-templatethat treats certain categories of types separately; You can templatize onfloatto treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaveragefunction a design flaw or a misuse? Because I doubt that aFloatclass (used asRet) encapsulating a built-infloatwould have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with anyRet.
– 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 isint, orlong, or..., orfloatordouble, orlong doubleor nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNumclass? Or a rational type? I do not expect the number of elements to exceedintever, but the operators provided byRetmay operate on any type thatintis 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
add a comment |
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.
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered yesterday
Aganju
4,9891621
4,9891621
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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 utilityclass-templatethat treats certain categories of types separately; You can templatize onfloatto treat the warning if you aren't concerned about precision loss;– WhiZTiM
2 days ago
Is the above
averagefunction a design flaw or a misuse? Because I doubt that aFloatclass (used asRet) encapsulating a built-infloatwould have a division operator with an integer. I don't see how to make the delegated utility class robust enough to work with anyRet.– 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, orlong, or..., orfloatordouble, orlong doubleor nothing else?– max66
2 days ago
It could be anything. Maybe a
BigNumclass? Or a rational type? I do not expect the number of elements to exceedintever, but the operators provided byRetmay operate on any type thatintis 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