How to initialize static std:array that uses static const variable as size? I tried searching for similar questions but std::array is relatively new so theres not much to be found.
// ExampleClass.h
class ExampleClass {
public:
static const size_t NUMBER_OF_INDEXES = 5;
private:
static std::array<int, NUMBER_OF_INDEXES> myArray;
};
Like any other static data member, ExampleClass::myArray should have an out-of-line definition in exactly one translation unit, where you write down its type and its qualified name as usual:
std::array<int, ExampleClass::NUMBER_OF_INDEXES> ExampleClass::myArray = {1, 2, 3, 4, 5};
Related
I know that in C++11, I can write
class foo {
static constexpr const char *one = "one";
}
However, when I try to do the same for an array
class bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
}
(and reference it later on) I get an undefined reference linker error.
Is this just not possible for arrays or am I missing something in the syntax?
Static constexpr data member declarations aren't definitions in C++11/14, therefore you cannot odr-use prim.
To work around it, put the following statement somewhere in your cpp file as you would do with any other non-constexpr static data member:
constexpr const float bar::prim[4];
In other terms, this returns an undefined reference:
struct bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
};
int main() {
auto *foo = bar::prim;
}
This doesn't:
struct bar {
static constexpr const float prim[4] = {2, 3, 5, 7};
};
constexpr const float bar::prim[4];
int main() {
auto *foo = bar::prim;
}
Because in the second case you are actually defining prim other than declaring it and thus you can get its address, use it by means of a reference, and so on...
I'm still fairly new to C++, so maybe its a very simple error I made here.
I wanted to initialize a private float array in one of my classes, like this.
float firstVect[] = {0.0f,0.0f,0.0f};
but firstVect is underlined with the explanation of incomplete type.
On the other hand two lines below the float array i have an int array looking like this:
int normalNumberOfDigits[]= {0,0,0};
The compile does not complain about the int array but only about the float array. Why?
Full code of my class:
class DataFilter
{
public:
int filterMovement(float vect3[3])
{
//TBD
}
private:
float firstVect[] = {0.0f,0.0f,0.0f};
int initialized = 0;
int normalNumberOfDigits[]= {0,0,0};
int determinNumberOfDigits(float testValue)
{
//TBD
}
};
Compiling with a modern version of clang++ makes your mistake obvious:
error: array bound cannot be deduced from an in-class initializer
You need to explicitly specify the size of the arrays (if you want to use a C-style array) in your class initialization:
class DataFilter
{
// ...
float firstVect[3] = {0.0f,0.0f,0.0f};
int initialized = 0;
int normalNumberOfDigits[3]= {0,0,0};
// ...
};
"The compile does not complain about the int array but only about the float array. Why?"
Compiling with a modern version of g++ makes this obvious as well:
error: flexible array member DataFilter::normalNumberOfDigits not at end of class DataFilter
When you declare an array without an explicit size, the compiler thinks that it is a flexible array, which is a C-only feature. It seems to be allowed in C++ as a non-standard g++ extension.
Non-static data members must have complete type, i.e. if they are arrays they must contain the array size. The size cannot be inferred from any initializers, because initializers are a) optional and b) not really part of the class definition, but rather implicitly part of all constructor function definitions.
Simple fix:
float firstVect[3] = {0.0f,0.0f,0.0f};
// ^^^
To clarify the explanation a bit: A class definition with default member initializer like this:
struct Foo
{
int a[3] = {1, 2, 3};
};
is conceptually the same as:
struct Foo
{
Foo();
int a[3];
};
Foo::Foo() : a{1, 2, 3} {}
You see now that the initializer is not really a part of the class definition, and thus cannot be used to deduce the array size.
A more extreme example is this:
struct Bar
{
Bar(int) : a{1, 2, 3} {}
Bar(float): a{1, 1} {}
Bar() = default;
int a[???] = {4, 4, 4, 4, 4};
};
What should the type of Bar::a be here?
Clang reports a clearer error:
fatal error: array bound cannot be deduced from an in-class initializer
You have to explicitly size your arrays:
class DataFilter
{
// ...
private:
float firstVect[3] = {0.0f,0.0f,0.0f};
int normalNumberOfDigits[3]= {0,0,0};
};
I would like to initalize a static const std::vector in class Foo to {0, 1, 2, 3, ..., n} where n is known at compile time based on the value of Last in the enum below. The goal is for Foo::all to contain all the values of the Fruit enum.
In foo.h:
enum Fruit { Apple, Orange, Banana, ..., Last };
class Foo {
public:
static const vector<int> all;
};
In foo.cpp:
// initialization of Foo::all goes here.
As a third option:
namespace {
std::vector<int> create();
}
const std::vector<int> Foo::all = create();
And create() can do anything it likes, even using push_back() for each element, because the vector it creates isn't const.
Or you could make create() a constexpr function using <index_tuple.h>
#include <redi/index_tuple.h>
namespace {
template<unsigned... I>
constexpr std::initializer_list<int>
create(redi::index_tuple<I...>)
{
return { I... };
}
}
const std::vector<int> Foo::all = create(typename redi::make_index_tuple<Last>::type());
You can use boost::irange:
auto range = boost::irange(0, n + 1);
const vector<int> Foo::numbers(range.begin(), range.end());
If your n is small enough and you use a compiler, which supports c++0x or c++11, just spell it out
const std::vector<int> Foo::all{0, 1, 2, 3, ..., n};
Fixed as per #Jonathan's explanation.
In Visual C++, how can I initialise a constant array inside of a class?
This is an example of how to do it outside of a class:
const char k_colors[] =
{
'R',
'G',
'B',
};
Now how do I need to change that? (I tried putting static in front of it, which didn't work)
Edit: You're right, I should just use single characters.
If you want it to be static, you'll need to initialize it outside the class:
class foo
{
public:
static const char k_colors[3];
foo() { }
};
const char foo::k_colors[] = {'a', 'b', 'c'};
Also, you probably want it to be a const char *[] since it looks like you're trying to initialize strings, so it'd be:
const char *foo::k_colors[] = {"Red", "Green", "Blue"};
I tried putting static in front of it, which didn't work
You can't initialise the static member array (or any member array) inside the class definition. Do it outside of the class definition:
class X
{
static const char* k_colors[3];
};
const char* X::k_colors[] = { "Red", "Green", "Blue" };
In C++11 you can use the constructor initializer list as mentioned
class A {
const int arr[2];
// constructor
A()
: arr ({1, 2})
{ }
};
Or you can use static const array
In header file:
class A {
static const int a[2];
// other bits follow
};
In source file (or in separate place from the declaration above)
const int A::a[] = { 1, 2 };
Of course you can always use std::vector<int> and for loop as well.
I think you can initialize through the constructor initializer list
Refer here
Also the char should be char*
Extract from the above link:
prior to C++11 you need to do just this to default-initialise each element of the array:
: k_colors()
With C++11 it is more recommended use uniform initialisation syntax:
: k_colors{ }
And that way you can actually put things into the array which you couldn't before:
: k_colors{"red","green"}
I have a class and I want to have some bit masks with values 0,1,3,7,15,...
So essentially i want to declare an array of constant int's such as:
class A{
const int masks[] = {0,1,3,5,7,....}
}
but the compiler will always complain.
I tried:
static const int masks[] = {0,1...}
static const int masks[9]; // then initializing inside the constructor
Any idea on how this can be done?
Thanks!
class A {
static const int masks[];
};
const int A::masks[] = { 1, 2, 3, 4, ... };
You may want to fixate the array within the class definition already, but you don't have to. The array will have a complete type at the point of definition (which is to keep within the .cpp file, not in the header) where it can deduce the size from the initializer.
// in the .h file
class A {
static int const masks[];
};
// in the .cpp file
int const A::masks[] = {0,1,3,5,7};
enum Masks {A=0,B=1,c=3,d=5,e=7};
you can initialize variables only in the constructor or other methods.
'static' variables must be initialized out of the class definition.
You can do this:
class A {
static const int masks[];
};
const int A::masks[] = { 1, 2, 3, 4, .... };
Well, This is because you can't initialize a private member without calling a method.
I always use Member Initialization Lists to do so for const and static data members.
If you don't know what Member Initializer Lists are ,They are just what you want.
Look at this code:
class foo
{
int const b[2];
int a;
foo(): b{2,3}, a(5) //initializes Data Member
{
//Other Code
}
}
Also GCC has this cool extension:
const int a[] = { [0] = 1, [5] = 5 }; // initializes element 0 to 1, and element 5 to 5. Every other elements to 0.