C++ template function that takes float or double - c++

I want to write a template function that will work on both double and float, something like that:
template <typename T>
constexpr auto someCalc(const T x) {
return x * 4.0 + 3.0;
}
My issue is that both 4.0 and  3.0 are doubles literal, thus I get the following error on clang:
error: implicit conversion increases floating-point precision: 'const float' to 'double' [-Werror,-Wdouble-promotion]
Is there an elegant way to write this code without having the up-conversion to double? The best I can come up with, is this
template <typename T>
constexpr auto someCalc(const T x) {
constexpr T four = 4.0;
constexpr T three = 3.0;
return x * four + three;
}
which I find less readable and harder to maintain for larger/more complicated function.

I would do it this way:
template <typename T>
constexpr auto someCalc(const T x) {
return x * T(4.0) + T(3.0);
}
Or with static_cast, if you prefer it.

While HolyBlackCat's answer is completely viable, here's my two bits:
Your constants are supposed to mean something in that particular situation. They likely are magic numbers with some meaning. The best course of actions is to give them a name, if you want make them maintenable. And in newer C++ it allows them to be templates
#include <iostream>
namespace sdd // some_dirty_details
{
/// #brief: Description of the constant
template <class T>
constexpr T some_constant = static_cast<T>(3.0);
}
int main()
{
std::cout << sdd::some_constant<float> << std::endl;
}

Related

Emulating the special properties of sizeof with constexpr

In C++ sizeof is somewhat unique in that it's legal to write this:
int x;
sizeof(x); // a variable
As well as simply:
sizeof(int); // a type
(There's a third even weirder variant I'd rather ignore for now though, with no parenthesis needed, since I'm pretty certain that is impossible to emulate)
I'd like to be able to replicate this behaviour myself. To motivate it I've got an example bitsof operator.
#include <climits>
template <typename T>
struct bits_traits {
enum { value = sizeof(T) * CHAR_BIT };
};
struct int_12_bit {
enum { bits = 12 };
// Let's pretent this has a bunch of code for looking and feeling like a 12bit int in a helpful and portable way
};
template <>
struct bits_traits<int_12_bit> {
enum { value = int_12_bit::bits };
};
#define bitsof(x) bits_traits<x>::value
int main() {
using std::size_t;
size_t b = bitsof(int);
size_t a = bitsof(int_12_bit);
int_12_bit x;
size_t c = bitsof(x); // <-- Not cool
}
Clearly I could have written the whole thing in terms of a macro, using sizeof, e.g.
#define bitsof(x) (sizeof(x) * CHAR_BIT)
But then I lose the ability to "specialise" it.
And equally I could write size_t c = bitsof(decltype(x)). However what I'm asking here is for a way of emulating that behaviour in my own code without having to settle for a workaround. How can I write a bitsof that looks and feels like sizeof, but specialises like traits? Do I just have to accept that sizeof is a bit special and live with it?
I initially played with a few ideas:
Perhaps decltype works like sizeof, e.g. decltype(0) and decltype(int) are synonymous. No luck there though.
Maybe we could do something with pointer/reference template parameters. I couldn't see a way of getting deduction to work properly for that case though, and it would impose additional constraints on what variables we could use bitsof with.
Maybe some crazy SFINAE with a combination of templates and macros, but I can't see a way of making that happen, it's always just a syntax error.
Possibly something to workaround the limitations of one of the above using GCC's statement-expr extension.
As there's an easy workaround with decltype and more of a learning experiment I'm open to ideas using anything available in any C++ released compiler targeting any past, present or future standard.
You can do something like this:
#include <type_traits>
#define bitsof(k) decltype(bitsof_left+(k)+bitsof_right)
template <class K>
struct bits_traits { /* whatever you want here */ };
struct bitsof_left_t {
template <class T>
bits_traits<T> operator+(const T&);
} bitsof_left;
struct bitsof_right_t {
template <class T>
friend T operator+(const T&, bitsof_right_t);
bitsof_right_t operator+();
template <class T>
operator T() const;
} bitsof_right;
int main()
{
using foo = bitsof(42);
using bar = bitsof(int);
static_assert(std::is_same<foo, bits_traits<int>>::value);
static_assert(std::is_same<bar, bits_traits<int>>::value);
}
It works like this.
a + (42) + b is parsed as (a + (42)) + b), then overloaded binary operator+ at either side kicks in. In my example the operators are only declared, not defined, but since it's unevaluated context, it doesn't matter.
a + (int) + b is parsed as a + ((int) (+ b)). Here we employ the overloaded unary + at the right side, then overloaded cast operator, then overloaded binary + at the left side.
Its hard and probably impossible, mainly because you can only pass compile-time constants as template values to templates, hence your last example with the int_12_bit x; will never be able to be a template value (and types can't be passed as parameters, of course). I played around a bit with decltype, declval and different templates, but I simply could not get it to take in types and (non-constand expression) values with a single "call". It's really unfortunate decltype doesn't accept types, I wonder why the committee choose to only accept expressions.
Since you mentioned gcc-extensions, there is an extension which can make it work, __typeof__.
I personally have never used this extension, but it seems like it works similar to decltype but it also accepts types directly.
This snipped compiles under gcc x86-64 8.3 for me:
template<typename T>
struct bits_trait;
template<>
struct bits_trait<int>{};
void f() {
int x;
bits_trait<__typeof__(x)>();
bits_trait<__typeof__(int)>();
}
But this will only compile under gcc.
Edit: Clang seems to support it as well, no luck with MSVC though.
Not considering macros and without decltype, it is simply not possible because of the language syntax.
However you can get pretty damn close:
template <class T>
constexpr auto bitsof(T) { return sizeof(T) * CHAR_BIT; }
template <>
constexpr auto bitsof(int_12_bit) { return 12; }
template <class T>
constexpr auto bitsof() { return sizeof(T) * CHAR_BIT; }
template <>
constexpr auto bitsof<int_12_bit>() { return 12; }
auto test()
{
constexpr int a{};
constexpr int_12_bit x{};
static_assert(bitsof(a) == 32);
static_assert(bitsof(x) == 12);
static_assert(bitsof<int>() == 32);
static_assert(bitsof<int_12_bit>() == 12);
}
Aside from the slightly different syntax (but c'mon it's so close it shouldn't really matter) the biggest difference to the sizeof is that the arguments are not in an unevaluated context. So bitsof(foo()) will call foo(). And bitsof(a) is UB if a is uninitialized.
Building upon the quite magical answer from n.m., with just tiny bit of massage, it seems it is possible to have bitsof mimic sizeof.
#include <climits>
#include <iostream>
#include <type_traits>
template <typename T>
struct bits_traits {
enum { value = sizeof(T) * CHAR_BIT };
};
struct int_12_bit {
enum { bits = 12 };
};
template <>
struct bits_traits<int_12_bit> {
enum { value = int_12_bit::bits };
};
#define bits_traits_of(k) decltype(bits_traits_of_left+(k)+bits_traits_of_right)
struct bits_traits_of_left_t {
template <class T>
bits_traits<T> operator+(const T&);
} bits_traits_of_left;
struct bits_traits_of_right_t {
template <class T>
friend T operator+(const T&, bits_traits_of_right_t);
bits_traits_of_right_t operator+();
template <class T>
operator T() const;
} bits_traits_of_right;
#define bitsof(x) bits_traits_of(x)::value
int main() {
using std::size_t;
size_t a = bitsof(int);
size_t b = bitsof(int_12_bit);
std::cout <<"a="<< a <<", b="<< b << std::endl;
int_12_bit x;
size_t c = bitsof(x);
std::cout <<"c="<< c << std::endl;
}
The only thing that I changed, other than adding in definitions for bits_traits, is to redefine bitsof so that it returns the bits_traits::value rather than the bits_traits type.
$ ./a.out
a=32, b=12
c=12
I'm just writing this up to verify that it can work. All credits should go to n.m.'s answer.

how to use the type of compile time constant primitive

How to use the type of a compile time constant primitive as type declaration for other variables?
I am trying to do some template metaprogramming in c++ for SI unit conversion. It comes down to how to automatically determine which primitive precision I need after one plus operator. For example:
template<typename Precision>
class Unit {
public:
Unit(Precision v) : value(v) {}
Precision value;
};
template<typename Precision1, typename Precision2>
struct PrecisionTransform {
constexpr static auto test = (Precision1)1 * (Precision2)1; // Compile time constant
using Type = Precision1; // TODO: ideally typeof(test)
};
template<typename Precision1, typename Precision2>
Unit<PrecisionTransform<Precision1, Precision2>::Type> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
return Unit<PrecisionTransform<Precision1, Precision2>::Type>(x.value + y.value);
}
int main()
{
Unit<double> a = 2.0;
Unit<float> b = 1.0f;
auto c = a + b;
return 0;
}
or in simple terms, can some thing like this happen?
float a = 1;
typeof(a) b = 2;
It seems quite possible since I've gone this far. But I am not sure how to use
You almost got it. As max66 already pointed out, use decltype. First of all, you can replace your PrecisionTransform class with the follwing type alias (you have to #include <utility> for this):
template <typename Precision1, typename Precision2>
using TransformType = decltype(std::declval<Precision1>() * std::declval<Precision2>());
The std::declval<XYZ>() is just a more generic way of saying (Precision1)1 which allows you to also use types that don't have accessible constructors (in your case irrelevant as you only use primitives).
Your operator+ is then changed to:
template<typename Precision1, typename Precision2>
Unit<TransformType<Precision1, Precision2>> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
return Unit<TransformType<Precision1, Precision2>>(x.value + y.value);
}
Note that you got a typo in your version of operator+ (both operands used Precision1).
As you can see here, the major compilers agree on this.

How to avoid narrowing conversion with floating point literals inside template functions

What do you usually do with floating point literals inside template functions?
Suppose that we have the following code:
template <typename T>
struct Foo
{
T bar;
};
template <typename T>
void foo(T val)
{
Foo<T> instance = { val * 5.0 };
}
int main()
{
foo(0.0f);
}
http://coliru.stacked-crooked.com/a/b159117097cc2461
It gives me the following warning / error (depending on the compiler / flags):
narrowing conversion of '(((double)val) * 5.0e+0)' from 'double' to 'float' inside { } [-Wnarrowing]
Foo<T> instance = { val * 5.0 };
How is it usually avoided? Should I just wrap any floating point literal in T(0.0) like:
Foo<T> instance = { val * T(5.0) };
Or is there any more elegant solution?
I would argue that T(5.0) is the most elegant solution. If T is a double then the conversion should be ignored by the compiler to which it is the same as writing 5.0. If T is a float then the conversion should resolved at compile time being equivalent writing as a float literal 5.0f.
If you are only dealing with a small number of well-defined magic constants but you need full control over the value of those constants for all possible Ts, it might make sense moving them to a traits class:
template<typename T>
struct FooTraits;
template<>
struct FooTraits<float> { static constexpr float magicN() { return 5.0f; } };
template<>
struct FooTraits<double> { static constexpr double magicN() { return 5.0; } };
template <typename T>
void foo(T val)
{
Foo<T> instance = { val * FooTraits<T>::magicN() };
}
This is some significant overhead in terms of boilerplate, so only do this if you actually need the added flexibility. If a simple cast to T works for all your use cases, there's nothing wrong with that.
How is it usually avoided?
I don’t think you should ‘avoid’ it as such, I’d say it depends on the final function semantics.
That is, if you want to disallow narrowing you use {} and let the compilation fail ( at least, as of >=c++11 );
if you want to allow narrowing to T on the final result you write instance = T( val * 5.0 ) and let converions do the rest for each possible T;
if you want to allow narrowing to T in intermidiate results or constants you wrap in T() there;
if you want the user to decide, you add a trait/policy class performing the final/intermidiate conversions …
that said, on one thing I'm sure: as a user of your function, I'd be very uncomfortable if any of the possibilities above were undocumented, or unreasonable given the function ultimate goal...
BTW, if you're question focuses only on constants, then I'd follow boost approach, maybe with the aid of c++14's variable templates.

The standard way to get sizeof(promoted(x)) [duplicate]

This question already has answers here:
Type trait to obtain default argument promotions
(3 answers)
Closed 7 years ago.
Is there a standard way to get the size of the type a variable would be promoted to when passed as a variadic argument?
auto x = ...;
auto y = sizeof(promoted(x));
The results should be:
char -> sizeof(int)
int -> sizeof(int)
float -> sizeof(double)
...
auto s = sizeof(+x);
should do the trick for integers.
+x makes use of the unary + operator, which performs integer promotion just like any other arithmetic operator.
I am not aware of any standard promotion rules for float that would apply here (in the integer promotion sense) since you can do arithmetic with them without promoting. If you always want to promote to at least double you can try
auto s = sizeof(x + 0.);
and then distinguish between floating point and integers before you get there.
Again, I do not think that you can handle integers and floating points at once because of the different meanings of "promotion" we are applying here.
We can simply declare overloaded promoted functions with the proper types:
int promoted(char);
int promoted(short);
int promoted(int);
long promoted(long);
long long promoted(long long);
double promoted(float);
double promoted(double);
long double promoted(long double);
Note that the functions need no implementations, because we are never actually calling them.
Here is a simple test run which prints 1, 4 and 4, 8 on my machine:
std::cout << sizeof('a') << '\n';
std::cout << sizeof(promoted('a')) << '\n';
std::cout << sizeof(3.14f) << '\n';
std::cout << sizeof(promoted(3.14f)) << '\n';
To generalise Baum mit Augen's answer, you could write function templates like this:
template <typename T>
auto promoted(T)
-> std::enable_if_t<std::is_integral<T>::value, decltype(+T{})>;
template <typename T>
auto promoted(T)
-> std::enable_if_t<std::is_floating_point<T>::value, decltype(T{}+0.)>;
//usage
sizeof(promoted(a))
Or a version using type traits:
template <typename T, typename = void>
struct promoted;
template <typename T>
struct promoted<T, std::enable_if_t<std::is_integral<T>::value>>
{ using type = decltype(+T{}); };
template <typename T>
struct promoted<T, std::enable_if_t<std::is_floating_point<T>::value>>
{ using type = decltype(T{} + 0.); };
template <typename T>
using promoted_t = typename promoted<T>::type;
//usage
sizeof(promoted_t<decltype(a)>)

c++ template double std::complex<double> norm and product

i wrote a template class that should work for double and std::complex. as it is suppose to be, all my methods are in the .hpp file. all but one. i had to specialize a method because at some place i have to compute the square of a double or the norm of a std::complex. more explicitly for the "double specialization" (A):
double a(2.0);
double b(0.0);
b = a*a;
for the "complex specialization" (B):
std::complex<double> a(2.0,3.0);
double b(0.0);
b = std::norm(a);
my questions are :
is there a way to avoid theses specializations by using a function that works for both double and complex ? (because the std::norm works only for complex...)
or the only solution is to cast the double a of the specialization (A) into a complex and then use only the specialization (B) as a general template (working for both double and complex)?
You can minimise the divergent case by introducing your own function as a square/norm wrapper:
template <typename T>
double square_or_norm(T x);
template<>
inline double square_or_norm(double x) { return x * x; }
template <>
inline double square_or_norm(std::complex<double> x) { return norm(x); }
Then, use it inside the function which needs it:
template <typename T>
T computation(T x) {
return some_code_with(x, square_or_norm(x));
}
You could define two function template overloads (when it comes to function templates, overloading is usually preferable to specialization) called compute_norm(), one accepting std::complex and one accepting unconstrained types. The unconstrained template would invoke operator *, while the constrained template would invoke std::norm().
#include <complex>
template<typename T>
double compute_norm(T t)
{ return t * t; }
template<typename T>
double compute_norm(std::complex<T> const& t)
{ return std::norm(t); }
Then, your generic code that can work both with a double and with a complex<double> would call compute_norm():
#include <iostream>
template<typename T>
void foo(T&& t)
{
// ...
double n = compute_norm(std::forward<T>(t));
std::cout << n << std::endl;
// ...
}
For instance, the following program:
int main()
{
double a(2.0);
foo(a);
std::complex<double> c(2.0, 3.0);
foo(c);
}
Will output:
4
13
Here is a live example.
If you have a conforming standard library, there is an overload of std::norm for floating point types:
26.4.9 Additional overloads [cmplx.over]
The following function templates shall have additional overloads:
arg norm
conj proj
imag real
The additional overloads shall be sufficient to ensure:
If the argument has type long double, then it is effectively cast to complex.
Otherwise, if the argument has type double or an integer type, then it is effectively cast to complex<
double>.
Otherwise, if the argument has type float, then it is effectively cast to complex.
This should work (and does on gcc 4.7.2)
#include <complex>
#include <iostream>
int main()
{
std::complex<double> c {1.5, -2.0};
double d = 2.5;
std::cout << "|c| = " << std::norm(c) << '\n'
<< "|d| = " << std::norm(d) << '\n';
}
Why not just use function overloading?
double myNorm(double);
double myNorm(std::complex<double>);
double myNorm(double x) {
return x * x;
}
double myNorm(std::complex<double> x) {
return std::norm(x);
}
You can put the implementation in your .cpp or (when inlined) in your header file.