patterncppMinor
Generic absolute value function
Viewed 0 times
absolutegenericfunctionvalue
Problem
I wanted to write a generic
Here is what I came up with:
The idea is to create a generic detail::abs
-
I chose to use
Here is a test case to demonstrate what the
abs function that would correctly work for every type. Basically, I wanted to use the following algorithm:- If the type is a built-in integer, use
std::absfrom `.
- If the type is a built-in floating-point, use std::abs
from.
- If the type is a user-defined type with a namespace-level abs
, use it.
- Otherwise, call a generic abs
algorithm.
Here is what I came up with:
#include
#include
namespace math
{
namespace detail
{
// generic abs algorithm
template
constexpr auto abs(const T& value)
-> T
{
return (T{}
constexpr auto abs(const T& value)
-> T
{
using std::abs;
using detail::abs;
return abs(value);
}
}The idea is to create a generic detail::abs
algorithm, then to create another abs function that will choose the function to call thanks to the argument-dependant lookup. Here is what I tried to take into account:
-
While the generic algorithm also works for built-in integral and floating point types, std::abs may produce optimized code for these types. Using std::abs when possible will probably generate an optimized executable. That said, std::abs lacks constexpr, which is a desirable feature, and the compiler might recognize a absolute value-like construct and optimize it away...
-
Some types have a namespace-level abs that does not behave like the generic algorithm. Therefore, we have to call this namespace-level function if it exist.
-
Some types may be huge. Therefore, I chose to take the parameter by const& since some namespace-level abs may also take their parameter by const&.
-
Some types only provide operator-
I chose to use
T{} instead of 0 for the comparison in the generic algorithm in order to be able to represent the default value for any given type. A type is not guaranteed to be comparable to an integer.Here is a test case to demonstrate what the
Solution
I believe you have a bug in your generic implementation, especially in relation to floating-point style classes that have signed-zero values:
your code:
would be better as a
Your current logic will return
Additionally, I don't know how you would really test these things, because, if I am not mistaken, in floating-point comparisons with signed-zero values,
How you resolve this issue though, I don't know.
your code:
return (T{} < value) ? value : -value;would be better as a
T{} value) ? -value : value;).Your current logic will return
-0.0 for an input value of 0.0, and that's not appropriate for an abs() function.Additionally, I don't know how you would really test these things, because, if I am not mistaken, in floating-point comparisons with signed-zero values,
-0.0 == 0.0 yet I would expect that abs(-0.0) would return 0.0.How you resolve this issue though, I don't know.
Code Snippets
return (T{} < value) ? value : -value;Context
StackExchange Code Review Q#60140, answer score: 5
Revisions (0)
No revisions yet.