My CPP understanding is not good enough to understand the following Class declaration
#define Default_n_datapoints 10
class MeanAngle {
public:
MeanAngle(std::size_t a_nDataPoints = Default_n_datapoints) :
NDATAPOINTS (a_nDataPoints) {};
virtual ~MeanAngle();
virtual void AddSample(const float a_fSample);
virtual float GetAverage() const;
protected:
const std::size_t NDATAPOINTS;
private:
float ring[NDATAPOINTS];
uint8_t i;
};
and in particular: If NDATAPOINTS is const, why can't I use it dimensioning ring[]? ring[NDATAPOINTS] gives me an error:
A non-static member reference must be relative to a specific object
How should I correct the declaration? What I want is that the initialisation parameter a_nDataPoints to be used as dimension in the ring buffer.
A specified array size must be a compile-time constant. That is, its value must be known at compile time. If you pretend that you are a C++ compiler, yourself, look at this code, and attempt to figure out what actual, integer, value NDATAPOINTS is, you will fall far short of your lofty goals.
The only thing that const gives you is that a const value is a run-time constant. It never changes once it exists. That's not the same thing as a compile-time constant. A compile-time constant would be a constexpr.
If you will always use this class with compile-time constant as argument, then you can make it template:
#include <cstdint>
static constexpr std::size_t Default_n_datapoints = 10ul;
template<std::size_t N = Default_n_datapoints>
class MeanAngle {
public:
MeanAngle() {};
virtual ~MeanAngle();
virtual void AddSample(const float a_fSample);
virtual float GetAverage() const;
protected:
const std::size_t NDATAPOINTS = N;
private:
float ring[N];
uint8_t i;
};
You can then use it like that:
MeanAngle<5> a;
MeanAngle<> b; // Default size will be used
Related
I have a class with a member function which declares an array whose size is based off a formula.
template <int SIZE>
class Example{
constexpr int lookup(const int n) const
{
return n * n + n;
}
inline void func()
{
double array[lookup(SIZE)];
}
};
This gives me the vla error. I think it should work because SIZE is resolved at compile time, and lookup is a constexpr. I know the following will work:
template <int SIZE>
class Example{
inline void func()
{
constexpr int sz = SIZE * SIZE + SIZE;
double array[sz];
}
};
I guess I'm just trying to figure out why
EDIT Sorry for the typos, was trying to just write a smaller example and ended up with the missing n and class name.
It's complicated...
First of all, some compilers (see MikeCAT answer and Bill Lynch linked example) can compile the following code (if you give a name to the class and correct lookup() naming n the argument)
inline void func()
{
double array[lookup(SIZE)];
}
because they support a C99 extension that accept the "variable length array" feature.
But this extension isn't standard C++.
You can verify this modifying func() as follows (almost equivalent, in standard C++)
inline void func()
{
constexpr int s = lookup(SIZE);
double array[s];
}
and this can't compile if lookup() is a non-static method
Consider that
lookup(SIZE);
is a short form for
this->lookup(SIZE);
I mean... the use of lookup() involve an object of your class.
The problem is that your func() method is available for both constexpr and non-constexpr objects.
Suppose you have a non-constexpr object: calling func() from it you impose that
constexpr int s = this->lookup(SIZE);
is evaluated compile-time.
That is: you impose that the this pointer (so the object itself) is available compile-time.
This is clearly impossible for run-time created objects, so your code can't compile.
Different if you declare lookup() as a static method: this way, calling lookup() doesn't involve an object of your class so your code can compile.
Class template must have a name.
n is not declared in lookup.
This should work as C++11:
template <int SIZE>
class hoge { // add hoge
constexpr int lookup(const int n) const // add n
{
return n * n + n;
}
inline void func()
{
double array[lookup(SIZE)];
}
};
I was trying to write a templated base class to store a fixed number of data types, each with varying length. Here is a simplified version of much what I was trying to do:
template< int NINT, int NR0 >
class EncapsulatedObjectBase
{
public:
EncapsulatedObjectBase();
~EncapsulatedObjectBase();
double m_real[NR0];
int m_int[NINT];
}
Yeah...so the template parameters can be zero, thus declaring a zero-length array of objects. There will be multiple derived classes for this base, each defining their own number of variables. I have two questions:
1) Is this approach fundamentally flawed?
2) If so...why doesn't icc13 or gcc4.7.2 give me warnings about this when I instantiate a zero-length array? For gcc I use -wall and -wextra -wabi. The lack of warnings made me think that this sort of thing was OK.
EDIT:
Here is the contents of a file that show what I am talking about:
#include <iostream>
template< int NINT, int NR0 >
class EncapsulatedObjectBase
{
public:
EncapsulatedObjectBase(){}
~EncapsulatedObjectBase(){}
double m_real[NR0];
int m_int[NINT];
};
class DerivedDataObject1 : public EncapsulatedObjectBase<2,0>
{
public:
DerivedDataObject1(){}
~DerivedDataObject1(){}
inline int& intvar1() { return this->m_int[0]; }
inline int& intvar2() { return this->m_int[1]; }
};
class DerivedDataObject2 : public EncapsulatedObjectBase<0,2>
{
public:
DerivedDataObject2(){}
~DerivedDataObject2(){}
inline double& realvar1() { return this->m_real[0]; }
inline double& realvar2() { return this->m_real[1]; }
};
int main()
{
DerivedDataObject1 obj1;
DerivedDataObject2 obj2;
obj1.intvar1() = 12;
obj1.intvar2() = 5;
obj2.realvar1() = 1.0e5;
obj2.realvar2() = 1.0e6;
std::cout<<"obj1.intvar1() = "<<obj1.intvar1()<<std::endl;
std::cout<<"obj1.intvar2() = "<<obj1.intvar2()<<std::endl;
std::cout<<"obj2.realvar1() = "<<obj2.realvar1()<<std::endl;
std::cout<<"obj2.realvar2() = "<<obj2.realvar2()<<std::endl;
}
If I compile this with "g++ -Wall -Wextra -Wabi main.cpp" I get no warnings. I have to use the -pedantic flag to get warnings. So I still don't know how unsafe this is. In retrospect, I feel as though it must not be a very good idea...although it would be pretty useful if I could get away with it.
Zero-sized arrays are actually illegal in C++:
[C++11: 8.3.4/1]: [..] If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero. The constant expression specifies the bound of (number of elements in) the array. If the value of the constant expression is N, the array has N elements numbered 0 to N-1, and the type of the identifier of D is “derived-declarator-type-list array of N T”. [..]
For this reason, your class template cannot be instantiated with arguments 0,0 in GCC 4.1.2 nor in GCC 4.7.2 with reasonable flags:
template< int NINT, int NR0 >
class EncapsulatedObjectBase
{
public:
EncapsulatedObjectBase();
~EncapsulatedObjectBase();
double m_real[NR0];
int m_int[NINT];
};
int main()
{
EncapsulatedObjectBase<0,0> obj;
}
t.cpp: In instantiation of 'EncapsulatedObjectBase<0, 0>':
t.cpp:17: instantiated from here
Line 10: error: ISO C++ forbids zero-size array
compilation terminated due to -Wfatal-errors.
clang 3.2 says:
source.cpp:10:17: warning: zero size arrays are an extension [-Wzero-length-array]
(Note that, in any case, you won't get any error until you do try to instantiate such a class.)
So, is it a good idea? No, not really. I'd recommend prohibiting instantiation for your class template when either argument is 0. I'd also look at why you want to have zero-length arrays and consider adjusting your design.
In C using a zero-sized array as the last member of a struct is actually legal and is commonly used when the struct is going to end up with some sort of dynamically-created inline data that's not known at compile-time. In other words, I might have something like
struct MyData {
size_t size;
char data[0];
};
struct MyData *newData(size_t size) {
struct MyData *myData = (struct MyData *)malloc(sizeof(struct MyData) + size);
myData->size = size;
bzero(myData->data, size);
return myData;
}
and now the myData->data field can be accessed as a pointer to the dynamically-sized data
That said, I don't know how applicable this technique is to C++. But it's probably fine as long as you never subclass your class.
1) Add to declaration of your class C++11 static_assert or BOOST_STATIC_ASSERT and you will have compile-time diagnostic for zero length array:
....
BOOST_STATIC_ASSERT(NR0 > 0);
BOOST_STATIC_ASSERT(NINT > 0);
double m_real[NR0];
int m_int[NINT];
};
2) Use std::array or boost::array and you will have run-time diagnostic (in debug mode) for index overflow problem in such code:
BOOST_STATIC_ASSERT(NR0 > 0);
BOOST_STATIC_ASSERT(NINT > 0);
boost::array<double, NR> m_real; //double m_real[NR0];
boost::array<int, NINT> m_int; //int m_int[NINT];
};
Remark:
class boost::array has specialisation for zero-size array
3) Use size_t but not int for size of array.
Your design is quite dangerous:
DerivedDataObject1 a;
a.m_real[2] = 1; // size of m_real == 0 !!!
I think it will better to change design of your class EncapsulatedObjectBase. May be it will better to use:
template<typename T, size_t N> class EncapsulatedObjectBase
{
....
};
class DerivedDataObject1 : public EncapsulatedObjectBase<int,2>
{
....
};
class DerivedDataObject2 : public EncapsulatedObjectBase<double,2>
{
....
};
class DerivedDataObject3 : public EncapsulatedObjectBase<double,2>
, public EncapsulatedObjectBase<int,2>
{
....
};
I'm constructing a class where I have three member variables that I want to always be the same value NO MATTER WHAT.
I have
class foo{
public:
double var_1, var_2, var_3;
double x=1, y=2, z=3;
[functions go here]
};
that gave me an error since I can't initialize a variable like that. But I want x, y and z to always be 1, 2 and 3 respectively. I tried defining them outside the class but that doesn't work since I want them to be member variables of the class.
How do I do this?
make these values static for the class, this way all object will inherit these same values.
static const int x = 1;
static const int y = 2;
static const int z = 3;
through technically, this does not define the variable. If a static data member is of const integral or const enumeration type, you may specify a constant initializer in the static data member's declaration. This constant initializer must be an integral constant expression. Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace.
#include "foo.h"
#include <//libs....>
int foo::x;
int foo::y;
int foo::z;
//class functions down below
You can also use an initializer list in the constructor to set these fields' initial values, just as with any other member:
class foo {
public:
const double x;
const double y;
const double z;
foo() : x(1), y(2), z(3) {
}
};
You don't have to make them static. You could declare them like this:
class foo{
public:
double var_1, var_2, var_3;
const double x=1.0;
const double y=2.0;
const double z=3.0;
[functions go here]
};
Though if they are integer values then declaring them as ints would be better.
How to declare a constant array in class with constant class variable? Is it possible.
I don't want dynamic array.
I mean something like this:
class test
{
const int size;
int array[size];
public:
test():size(50)
{}
}
int main()
{
test t(500);
return 0;
}
the above code gives errors
No, it's not possible: As long as size is a dynamic variable, array[size] cannot possibly be implemented as a static array.
If you like, think about it this way: sizeof(test) must be known at compile time (e.g. consider arrays of test). But sizeof(test) == sizeof(int) * (1 + size) in your hypothetical example, which isn't a compile-time known value!
You can make size into a template parameter; that's about the only solution:
template <unsigned int N>
class Test
{
int array[N];
static const unsigned int size = N; // unnecessary really
public:
// ...
};
Usage: Test<50> x;
Note that now we have sizeof(Test<N>) == sizeof(int) * (1 + N), which is in fact a compile-time known value, because for each N, Test<N> is a distinct type.
You mean a fixed sized array? You could use std::array like this:
#include <array>
class test
{
static const size_t s_size = 50;
std::array<int, s_size> m_array;
public:
test()
{
}
};
Or if you want to support different sizes you need to resort to a class template like this:
#include <array>
template <size_t SIZE>
class test
{
std::array<int, SIZE> m_array;
public:
test()
{
}
};
std:array has the added benefit of keeping the size information along with the member (unlike arrays which decay to pointers) and is compatible with the standard library algorithms.
There is also a version that Boost offers (boost::array) which is similar.
Your code yields an error because compiler needs to know the size of data type of each member. When you write int arr[N] type of member arr is "an array of N integers" where N must be known number in compile time.
One solution is using enum:
class test
{
enum
{
size = 50
};
int arr[size];
public:
test() {}
};
Another is declaring size as static const member of class:
class test
{
static const int size = 50;
int arr[size];
public:
test(){}
};
Note that in-class initialization is allowed only for static class integers! For other types you need to initialize them in code file.
If I have a class that defines multiple constant variables like so...
class SomeClass {
public:
SomeClass() : SOME_CONSTANT(20), ANOTHER_CONSTANT(45), ANOTHER_CONSTANT2(25), ANOTHER_CONSTANT2(93) { }
private:
const int SOME_CONSTANT;
const int ANOTHER_CONSTANT;
const int ANOTHER_CONSTANT2;
const int ANOTHER_CONSTANT3;
Will multiple instances of this class be optimized to point to the same memory for the constants? or can I save memory by making each constant static?
If they are not static, then no, they will not be optimized out. Each instance will have space for all the constants. (In fact, I don't think the compiler is even allowed to combine them in any way.)
If you do declare them static, they are in global memory and not in each instance. So yes, it will use less memory.
EDIT:
If you want to make them static constants, it should be done like this:
class SomeClass {
public:
SomeClass(){ }
private:
static const int SOME_CONSTANT;
static const int ANOTHER_CONSTANT;
static const int ANOTHER_CONSTANT2;
static const int ANOTHER_CONSTANT3;
};
const int SomeClass::SOME_CONSTANT = 20;
const int SomeClass::ANOTHER_CONSTANT = 45;
const int SomeClass::ANOTHER_CONSTANT2 = 25;
const int SomeClass::ANOTHER_CONSTANT3 = 93;
How about an enumeration instead?
class SomeClass {
public:
SomeClass() { }
private:
enum {
SOME_CONSTANT = 20,
ANOTHER_CONSTANT = 45,
ANOTHER_CONSTANT2 = 25,
ANOTHER_CONSTANT3 = 93
};
};
An enumeration guarantees that the constants won't take up any memory at all.
Declared this way, all instances of this class will have its own copies. To avoid this and save memory, declare them as static.
Note: don't forget to define them outside the class. As these are ints, you may avoid defining them outside the class, this actually depends more on the compiler, than the standard (yes, I know how ridiculous this soudns). I can't test it now, but I remember, that gcc and VS have different behaviors about this.
So, you may need to do this:
class SomeClass {
public:
SomeClass()
{ }
private:
static const int SOME_CONSTANT;
static const int ANOTHER_CONSTANT;
static const int ANOTHER_CONSTANT2;
static const int ANOTHER_CONSTANT3;
const int SomeClass::SOME_CONSTANT = 20;
//.. the same for the others.
EDIT I'll find this part of the standard (the exception for integral types) and post it here + tests on both compilers later today :) )
You cannot make those constants static - simply because your constructor initialses them!
SomeClass() : SOME_CONSTANT(20), ANOTHER_CONSTANT(45), ANOTHER_CONSTANT2(25), ANOTHER_CONSTANT2(93) { }
Remove those initialisers i.e.
SomeClass{};
static const int SOME_CONSTANT = 20;
Then you will have just one int for the class.
You can try checking the sizeof() of an instance of the class. I don't think they'll be optimized out. Using const static variables for this purpose will probably be the right thing to do, especially if they are all integers, in which case you can initialize them at the definition and get compile time constants without worrying about static objects initialization order.
class SomeClass
{
private:
const static int SOME_CONSTANT = 20;
const static int ANOTHER_CONSTANT = 45;
const static int ANOTHER_CONSTANT2 = 25;
const static int ANOTHER_CONSTANT3 = 93;
};