What is the reason for not being able to deduce array size from initializer-string in member variable?
The reason is that you always have the possibility to override an in-class initializer list in the constructor. So I guess that in the end, it could be very confusing.
struct Foo
{
Foo() {} // str = "test\0";
// Implementing this is easier if I can clearly see how big `str` is,
Foo() : str({'a','b', 'c', 'd'}) {} // str = "abcd0"
const char str[] = "test";
};
Notice that replacing const char
with static constexpr char
works perfectly, and probably it is what you want anyway.
What is the reason for not being able to deduce array size from initializer-string in member variable?
The reason is that you always have the possibility to override an in-class initializer list in the constructor. So I guess that in the end, it could be very confusing.
struct Foo
{
Foo() {} // str = "test\0";
// Implementing this is easier if I can clearly see how big `str` is,
Foo() : str({'a','b', 'c', 'd'}) {} // str = "abcd0"
const char str[] = "test";
};
Notice that replacing const char
with static constexpr char
works perfectly, and probably it is what you want anyway.
In class default initializer for array member C++11
A default member initializer is just that - the default. It always allows for the possibility that a constructor will provide a different value. num2letter
could potentially be initialized from one of Example
's constructors, at which point the default initializer wouldn't even be used... so the type has to be explicitly provided. The declaration has to be valid with our without the initializer.
This is the same reason that you can't do something like:
class Example {
auto i = 4;
};
Deduce std::array size?
C++17 std::array
class template argument deduction (CTAD)
Starting with C++17, this new language feature is now used by the standard library and now allows us to omit the template types as well so that the following works:
main.cpp
#include <array>
int main() {
std::array a{1, 2, 3};
}
instead of std::array<int, 3> a{1, 2, 3};
Tested with:
g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp
If we set -std=c++14
instead for example, it fails to compile with:
error: missing template arguments before ‘a’
Tested on Ubuntu 18.04, GCC 7.5.0.
Why I cannot initialize char array in struct
The problem is that array extent cannot be deduced automatically from an in-class initializer. The error message produced by clang is quite clear (see here):
prog.cc:4:34: error: array bound cannot be deduced from an in-class initializer
const char value_in_struct[] = "a";
^
So why is this? In-class initializer can be overridden by a member initializer list of a constructor. So, what if a constructor chooses to initialize the array with something else? In your case, the initializer can be overridden with a brace-enclosed initializer list as follows (aggregate initialization, actually) (see here):
A a = {"abc"};
Since the ultimate initializer cannot be determined at compile time, the compiler cannot deduce the array extent.
Giving the array an explicit extent makes the code compile (see here).
#include <iostream>
struct A {
const char value_in_struct[2] = "a";
};
void t(void) {
char value[] = "a";
std::cout << "value = " << value << std::endl;
}
How to initialize all members of an array to the same value?
Unless that value is 0 (in which case you can omit some part of the initializer
and the corresponding elements will be initialized to 0), there's no easy way.
Don't overlook the obvious solution, though:
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
Elements with missing values will be initialized to 0:
int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...
So this will initialize all elements to 0:
int myArray[10] = { 0 }; // all elements 0
In C++, an empty initialization list will also initialize every element to 0.
This is not allowed with C until C23:
int myArray[10] = {}; // all elements 0 in C++ and C23
Remember that objects with static storage duration will initialize to 0 if no
initializer is specified:
static int myArray[10]; // all elements 0
And that "0" doesn't necessarily mean "all-bits-zero", so using the above is
better and more portable than memset(). (Floating point values will be
initialized to +0, pointers to null value, etc.)
C++ Sized template deduction
with C++20 you can achieve this by adding 2 user defined deduction guides:
template<typename... Ts>
JsonPointer(Ts... ts)->JsonPointer<sizeof...(Ts)>;
template<size_t S>
JsonPointer(JsonPointer<S> existing, const char* suffix)->JsonPointer<S + 1>;
they allow the compiler to find the correct deduction without naming the full template.
template<size_t L>
class JsonPointer {
public:
constexpr JsonPointer(std::array<const char*, L> segments)
: m_path_segments(std::move(segments))
{
}
constexpr JsonPointer(std::initializer_list<const char*> list) : m_path_segments() {
std::copy(list.begin(), list.end(), this->m_path_segments.begin());
}
template<size_t S>
constexpr JsonPointer(JsonPointer<S> existing, const char* suffix) : m_path_segments() {
std::copy(existing.m_path_segments.begin(), existing.m_path_segments.end(),
this->m_path_segments.begin());
this->m_path_segments.back() = std::move(suffix);
}
template<size_t S>
friend class JsonPointer;
private:
std::array<const char*, L> m_path_segments;
};
template<typename... Ts>
JsonPointer(Ts... ts)->JsonPointer<sizeof...(Ts)>;
template<size_t S>
JsonPointer(JsonPointer<S> existing, const char* suffix)->JsonPointer<S + 1>;
int main() {
constexpr JsonPointer base_ptr{ "a", "n" };
constexpr auto ptr = JsonPointer(base_ptr, "test");
}
the constexpr ptr
now holds {"a", "n", "test"}
try it out
Related Topics
Cycles in Family Tree Software
Why Use Prefixes on Member Variables in C++ Classes
What Does the Fpermissive Flag Do
Boost::Flat_Map and Its Performance Compared to Map and Unordered_Map
How to Solve the Error Lnk2019: Unresolved External Symbol - Function
How to Output the Value of an Enum Class in C++11
Typeid' Versus 'Typeof' in C++
How to Convert a Char Array to a String
How to Append a Char to a Std::String
Why How to Access Private Variables in the Copy Constructor
How to Alpha Blend Rgba Unsigned Byte Color Fast
How to Download the Visual C++ Command Line Compiler Without Visual Studio
Why Does Visual Studio 2013 Error on C4996