The following
int i = 0;
double d{i};
gives an error (in clang) or warning (in gcc) of a narrowing conversion from 'int' to 'double'
. I found it amazing that this is really narrowing, at least until I saw narrowing conversion from unsigned to double.
My actual problem originates from a class that contains an array and provides a constructor for specifying the elements of the array, in the simplest way possible (forwarding):
template<typename T, size_t N>
struct A
{
T a[N];
template<typename... E>
A(E&&... e) : a{std::forward<E>(e)...} { }
};
In this case, we have the following (live example):
int i = 0;
A<double, 2> x(i, 2); // ERROR for both 'i' and '2'
double y[2]{i, 2}; // ERROR for 'i' only
where ERROR
refers to narrowing conversion as discussed above. I suspect that all those errors boil down to the one mentioned at the beginning (double d{i};
). Is this so? Otherwise, what is happening?
Anyhow, I would really like
A<double, 2> x(i, 2);
to work, exactly as
double x(i);
works. Unfortunately, I can only initialize the array using an initializer list, which also checks for narrowing conversions. I know one workaround is to make an explicit cast in the constructor:
template<typename... E>
A(E&&... e) : a{static_cast <T>(e)...} { }
or (thanks Marc)
template<typename... E>
A(E&&... e) : a{static_cast <T>(std::forward<E>(e))...} { }
but is this the "right" way? And is it the most efficient, when E
is a "large" type?
forward
? Trystatic_cast<T>(forward<E>(e))
with a type that prints something on copying, and notice that your cast is free. – Veinfoo
type exactly for such experiments (copying, moving, everything), and I will try now. Thanks. I'll also update it in the question. – Jemptystatic_cast<T>
). So is this the right way? Nothing else needed? – Jempty