Array initialization with identical elements
Here's a compile time solution that uses initialisation (uses std::array
instead of a C array):
template<std::size_t N, typename T, std::size_t... Is>
constexpr std::array<T, N> make_filled_array(
std::index_sequence<Is...>,
T const& value
)
{
return {((void)Is, value)...};
}
template<std::size_t N, typename T>
constexpr std::array<T, N> make_filled_array(T const& value)
{
return make_filled_array<N>(std::make_index_sequence<N>(), value);
}
auto xs = make_filled_array<300, int>(10);
auto ys = make_filled_array<300>(10);
In struct nested union/array member default initialization compiles, but is not happening correctly?
What you are doing is aggregate initialization, which means the elements in sArray
and dArray
are value initialized when not specified. Because short
and double
are scalar types, this means zero initialization
Since you don't specify anything but the first element, all remaining elements will be initialized to 0
As requested in the comments, a way to initialize the arrays would be std::fill
or std::fill_n
:
#include <algorithm>
struct Nested {
explicit Nested() {
std::fill_n(sArray, 5, 0);
std::fill_n(dArray, 5, 0.0);
}
union {
short sArray[5];
float fVal; // Must NOT be initialized - obviously, only 1 member of a
// union can be
};
double dArray[5];
};
In general, I would recommend to instead use std::array
and its fill
function:
#include <array>
struct Nested {
explicit Nested() {
sArray.fill(0);
dArray.fill(0.0);
}
union {
std::array<short, 5> sArray;
float fVal; // Must NOT be initialized - obviously, only 1 member of a
// union can be
};
std::array<double, 5> dArray;
};
Getting root type of multidimensional variadic std::array
You can use a basic recursive technique:
template <typename T>
struct nested_value_type { using type = T; };
template <typename T, std::size_t N>
struct nested_value_type<std::array<T, N>>
{
using type = typename nested_value_type<T>::type;
};
Provide an alias template for convenience:
template <typename T>
using nested_value_type_t = typename nested_value_type<T>::type;
And voila:
static_assert(std::is_same_v<
nested_value_type_t<std::array<int, 1>>,
int
>);
static_assert(std::is_same_v<
nested_value_type_t<std::array<std::array<float, 1>, 1>>,
float
>);
static_assert(std::is_same_v<
nested_value_type_t<std::array<std::array<std::array<char, 1>, 1>, 1>>,
char
>);
live example on godbolt.org
A bit shorter with C++20's std::type_identity
:
template <typename T>
struct nested_value_type : std::type_identity<T> { };
template <typename T>
using nested_value_type_t = typename nested_value_type<T>::type;
template <typename T, std::size_t N>
struct nested_value_type<std::array<T, N>>
: std::type_identity<nested_value_type_t<T>> { };
Narrowing conversions in C++0x. Is it just me, or does this sound like a breaking change?
I ran into this breaking change when I used GCC. The compiler printed an error for code like this:
void foo(const unsigned long long &i)
{
unsigned int a[2] = {i & 0xFFFFFFFF, i >> 32};
}
In function
void foo(const long long unsigned int&)
:error: narrowing conversion of
(((long long unsigned int)i) & 4294967295ull)
fromlong long unsigned int
tounsigned int
inside { }error: narrowing conversion of
(((long long unsigned int)i) >> 32)
fromlong long unsigned int
tounsigned int
inside { }
Fortunately, the error messages were straightforward and the fix was simple:
void foo(const unsigned long long &i)
{
unsigned int a[2] = {static_cast<unsigned int>(i & 0xFFFFFFFF),
static_cast<unsigned int>(i >> 32)};
}
The code was in an external library, with only two occurrences in one file. I don't think the breaking change will affect much code. Novices might get confused, though.
Related Topics
What Are Transparent Comparators
What Is the Purpose of the Most Vexing Parse
Difference Between Static and Dynamic Arrays in C++
How to Use Sdl2 in My Programs Correctly
Converting Std::_Cxx11::String to Std::String
Which, If Any, C++ Compilers Do Tail-Recursion Optimization
Is a String Literal in С++ Created in Static Memory
What Are the Mechanics of Short String Optimization in Libc++
Capturing Function Exit Time With _Gnu_Mcount_Nc
How Does the Import Library Work - Details
Do You Use Null or 0 (Zero) For Pointers in C++
Strptime() Equivalent on Windows
Detecting Signed Overflow in C/C++
Is It Better to Use Std::Memcpy() or Std::Copy() in Terms to Performance
Is the Practice of Returning a C++ Reference Variable Evil
"Undefined Reference To" Errors When Linking Static C Library With C++ Code
Is Uninitialized Local Variable the Fastest Random Number Generator