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 throughbegin()
andend()
member funcitons. I may need to addconst&
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 intoRet
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. Anint
may match only one of the overloads - so there is no ambiguity, butdecltype
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
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 range
is any object that defines a range throughbegin()
andend()
member funcitons. I may need to addconst&
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 intoRet
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. Anint
may match only one of the overloads - so there is no ambiguity, butdecltype
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
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-template
that treats certain categories of types separately; You can templatize onfloat
to treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaverage
function a design flaw or a misuse? Because I doubt that aFloat
class (used asRet
) encapsulating a built-infloat
would 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..., orfloat
ordouble
, orlong double
or nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNum
class? Or a rational type? I do not expect the number of elements to exceedint
ever, but the operators provided byRet
may operate on any type thatint
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
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 range
is any object that defines a range throughbegin()
andend()
member funcitons. I may need to addconst&
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 intoRet
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. Anint
may match only one of the overloads - so there is no ambiguity, butdecltype
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
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 throughbegin()
andend()
member funcitons. I may need to addconst&
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 intoRet
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. Anint
may match only one of the overloads - so there is no ambiguity, butdecltype
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
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-template
that treats certain categories of types separately; You can templatize onfloat
to treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaverage
function a design flaw or a misuse? Because I doubt that aFloat
class (used asRet
) encapsulating a built-infloat
would 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..., orfloat
ordouble
, orlong double
or nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNum
class? Or a rational type? I do not expect the number of elements to exceedint
ever, but the operators provided byRet
may operate on any type thatint
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
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-template
that treats certain categories of types separately; You can templatize onfloat
to treat the warning if you aren't concerned about precision loss;
– WhiZTiM
2 days ago
Is the aboveaverage
function a design flaw or a misuse? Because I doubt that aFloat
class (used asRet
) encapsulating a built-infloat
would 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..., orfloat
ordouble
, orlong double
or nothing else?
– max66
2 days ago
It could be anything. Maybe aBigNum
class? Or a rational type? I do not expect the number of elements to exceedint
ever, but the operators provided byRet
may operate on any type thatint
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
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-template
that treats certain categories of types separately; You can templatize onfloat
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 aFloat
class (used asRet
) encapsulating a built-infloat
would 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..., orfloat
ordouble
, orlong 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 exceedint
ever, but the operators provided byRet
may operate on any type thatint
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