const declaration inside the class - c++

to avoid complicated linker rules, C++ requires that every object has
a unique definition. That rule would be broken if C++ allowed in-class
definition of entities that needed to be stored in memory as objects.
I'm having hard time understanding this:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
static const int c6 = 7;
};
How does const int c6 = 7; break following rule?
C++ requires that every object has
a unique definition.
And static const int c6 = 7; do not break it (enums too)?
Please also explain why static const float c5 = 7; is not allowed but static const int c5 = 7; is allowed?

A lot of these rules have been changing over time, so it really depends on the version of C++ you are using. Also, some of these may not be technically impossible, but the committee simply decided against them because they might be hard to implement, or are prone to errors. So you might not always get the most satisfying answer on why thing are the way they are.
Lets go over them one by one.
Const Member
class Foo
{
const int bar = 7;
};
This used to be illegal before C++11. Before that version you were only allowed to initialize static variables in their declaration. If you are still not on C++11, my condolences. More details can be found here.
Static Member
class Foo
{
static int bar = 7;
};
Another one that changed, but more recently. Before C++17 it was illegal to initialize non const static variables in their declaration. This has to do with the one definition rule. When the header containing this class is included in multiple translation units (.cpp files), which one should be responsible for initializing the value? This is why you have to place the definition somewhere in a single .cpp file.
After C++17 you are allowed to do this:
class Foo
{
inline static int bar = 7;
};
When you use inline like this it somehow figures out how to only initialize it once. More details can be found here.
Static Const Float Member
class Foo
{
static const float bar = 7.0f;
};
This has mainly to do with the unpredictability of floats when you run into floating point errors. An example:
class Foo
{
static const float bar = 0.1f;
};
Since 0.1f is impossible to represent in most floating point implementations, you won't get exactly 0.1f, but only something very close to it. This can then result in different behaviors on different systems that have slightly different implementations, causing your program to run differently depending on the system.
This gets even worse when the value is the result of a calculation, because (a*b)*c is not guaranteed to be the exact same value as a*(b*c), even though it might seem like they are.
But const static floats are still allowed when you define the value outside of the class, so technically it would all still be possible to implement. But the committee never did, probably because it would cause more problems than it would solve. This is also similar to why you are allowed to use integral types as template parameters, but not floats.
template <int i> class Foo {}; // Good
template <float f> class Bar {}; // Bad
However, the committee seems to have changed it's opinion somewhat, since we are now allowed to use floats with constexpr. So it can be done if you write this instead:
class Foo
{
static constexpr float bar = 7.0f;
};
Conclusion
All of these are actually possible in some form with the right version of C++ and the right syntax. Just keep in mind the potential issues described above, and you should be good to go.

Let go through it.
FIRST READ BELOW THEN COME TO CODE
class Y {
const int c3 = 7; // It's fine. If you write good constructor.
// static int c4 = 7; // error: not const as it is trying to initialize with object constructor which it shouldn't
static const float c5 = 7; // error: not integral as we can do it for integral type only. To correct this you can do.
static constexpr float c5 = 7; // we should use constexpr for literal type.
static const int c6 = 7; // it was fine as both types are same int and 6 where it was not the case in 1st case.
};
int main()
{
Y y;
}
First, learn these lines
a. When we create a const object of a class type, the object does not
assume its constness until after the constructor completes the object's initialization.
Thus, constructors can write to const objects during their construction.
So this will yield an error.
class Const {
public:
Const(int ii);
private:
int i;
const int ci;
};
ConstRef::ConstRef(int ii)
{ // assignments:
i = ii; // ok
ci = ii; // error: cannot assign to a const
}
**TO CORRECT THIS YOU SOULD DO**
Const::Const(int ii): i(ii), ci(ii) { } // this is how constructor should be
Let's discuss everything one by one.
Your fist member is already excellent. It should work fine as per my knowledge, and it's working for me. I think it's not working for you because your constructor is trying to initialize it in the constructor body, which you can't.
We must use the constructor initializer list to provide values for members that
are const, reference, or of a class type that does not have a default
constructor.
Let come to the static part
We say a member is associated with the class by adding the keyword static to its declaration.
The static members of a class exist outside any object.
static member functions are not bound to any object; they do not have
a this pointer. As a result, static member* functions* may not be declared as const, and we may not refer to this in the body of a static member. This restriction applies both to explicit uses of this and to implicit uses of this by calling
a nonstatic member.
IMP
Because static data members are not part of individual objects of the class type, they are not defined when we create objects of the class. As a result, they are not initialized by the class’ constructors. Moreover, in general, we may not initialize a static member inside the class.
So i think you got your second error reason. You are trying to initialize it with object constructor.
Let's go to the third one.
Ordinarily, class static members may not be initialized in the class body. However, we can provide in-class initializers for static members that have const integral
type and must do so for static members that are constexprs of literal type. The initializers must be constant expressions.
So.
static constexpr float c = 7; this is fine. You can check
I hope it' clear now. Let m know if you still got issues. Btw i skipped indirect concept too. But for depth understanding you need to learn about ``literal class`.

Related

const object or private/const data members (variables) in C++?

We know that const object members cannot be modified once declared but what is the real use of them? We can individually declare variables to be const inside the class or declare them private.
If there is any other significance of const object in C++, then please mention that too.
To answer your question literally:
If you make members of a class const, that applies to every instance of the class, but only to the members that you made const.
If you make an object const, that applies to a single instance of that class, but it does apply to all members of that instance.
const is one of the most elementary subjects in C++, in my opinion. Something that is way too often overlooked.
Generally const has three use cases:
Allowing the compiler to optimize more aggressively
Allowing the compiler to point out our mistakes when we accidentally try to change a const value
Convey intend by specifying that we do not want an object changed
In the case of a const member of a class, we force the object to be initialized during instantiation of the class. Preventing us from accidentally changing it's value in member functions. Which is the big difference to just using a private member variable. We still can accidentally change a private member variable anywhere inside the class.
One of the most useful ways to use const is with parameters:
This can allow major optimization for the compiler, for various reasons that are out of scope of this answer.
And in the case of const references, the compiler can prevent you from accidentally changing the value of that reference.
Most importantly, it allows you to define the signature of your function in a more clarifying way.
I luckily use this once(so far). And i never thought i would need to use a const in a member variable.
class TypeA {
protected:
DataX const* m_data; //get a pointer to a data that shouldn't be modified even inside the class.
public:
TypeA(DataX const* p){
m_data = p;
}
auto& getData(){ return *m_data; } //will return DataX const&
}
For the private member variables, i think they are best for helper-variables in the current class that are really not part of the object logically. Maybe for caching, temporary holder of some data that should be there for a time duration, a counter for an algorithm, etc. And they are only used and should be used in the current class. You don't want other programmers to use them in the derived class because they have a very special use so you hide them in private.
Another example for const member are for constant values aside for enums. I prefer enum over a variable that takes storage but some programmer prefer following on what they used to however you convinced them not to(maybe i'm wrong, and they are really correct, and maybe in the future for some reason the const in the language changed, and then using const might be better.)
class TypeA {
public:
const int HEY_VALUE = 101;
const int YOH_VALUE = 102;
const int HELP_VALUE = 911;
const float MIN_SOMETHING = 0.01;
static const int HELLO_EARTH = 10;
//...
}
I can't find this specific code of mine, but i think i used & instead of const*. I used it like this.
class TypeA {
protected:
DataX& m_data;
public:
TypeA(DataX& p):m_data(p){ //you can only set this once in the constructor
}
auto& getData(){ return m_data; } //will return DataX const&
}
I really prefer using . instead of -> for personal reasons so I really pushing myself to achieve the syntax i want and i came with these weird solutions. It's fun because I discovered that those weird approaches are still valid and achievable in c++.
Update
If there is any other significance of const object in C++, then please mention that too.
Maybe you can const some filler bytes on specific part of the class.
class TypeA {
protected:
const int HEADER_BYTES = 0x00616263;
int m_data1;
int m_data2;
const uint8_t ANOTHER_FILLER_FOR_SOME_REASON = 0xffffffff; //maybe forcing offset address, or alignment, etc.
int m_anotherData;
}
Generally, const keyword is being used to improve readability of the code you are writing.
However, in some cases const can also allow compiler optimizations. Let's see the following code snippet:
int const i = 1;
fun(&i);
printf("%d\n", i);
Here, trying to modify the variable i would cause an Undefined Behaviour. Therefore, the compiler will assume modification won't be even tried so it will pass the value 1 to the printf function.
Same is valid for const data members.

Does pointer-to-member make sense for a static member?

The pointer-to-member feature of C++ is interesting and powerful, but I'm wondering if it is or should be limited only to instantiated objects of a class, or if it is okay to point to a static member? The use cases aren't obvious to me for either static or non-static usage of the feature, though it does seem very interesting.
Pointers to statics are actually "normal" pointers, e.g.
class MyClass
{
public:
static int x;
static int f(int a)
{
return a+1;
}
};
// ...
int* pint = &MyClass::x; // pointer to static property
int (*pfunc)(int) = &MyClass::f; // pointer to static method
Pointers to non-static members are "special" because they need a class instance to dereference a value. They can be thought of as "offset of a member inside a class instance" (this is very rough, though, and cannot be applied to method pointers!).
Static members, on contrast, are actually much like namespaced global variables, possibly with restricted visibility. They have static memory addresses, which are independent of class instances — all instances share a single static member.
The following is legal C++11 code.
struct X
{
static void f() {}
static int i;
X() = delete;
};
typedef void(*funcPtr)();
int main()
{
funcPtr g = &X::f;
int * j = &X::i;
}
There is nothing wrong about taking adresses of static member data and functions. As you can see the class never gets instantiated at any time.

Is it better to replace constants by template parameters?

Is it better to do:
const int MY_CONST = 20; // global constant in the program
class A {
// uses MY_CONST all over the class implementation and definition
}
or this?
const int MY_CONST = 20; // global constant in the program
template<int my_const>
class A {
//uses my_const only and never MY_CONST
};
//A<MY_CONST> used later in the program
Is one of these pattern better than the other? why?
thanks
Unless that global constant is used elsewhere outside of the class I would use neither of those approaches and make the constant a member of A:
class A {
public:
static const int MY_CONST = 20;
};
const int A::MY_CONST; // Possibly need definition also
And then use A::MY_CONST in your code.
The only time I would use a template is when you need to change the value depending on the instance for some reason.
template <int I>
class A
{
public:
static const int MY_CONST = I;
};
template <int I>
const int A<I>::MY_CONST; // Definition
Then create instances like so:
A<1> a1;
A<2> a2;
The second solution is sensible if it makes sense to instantiate e.g. A<MY_CONST + 1>, or A<0>, or any other value than MY_CONST. If, however, A is strictly designed to be used with the one value, then you don't gain anything from that. In that respect the first solution gives you everything you need.
One way to look at it is that you're introducing a dependency to A (only on a number, not on anything with behavior, but still that's a kind of dependency), and the question is whether to inject that dependency via a template parameter, or have the class pull in the dependency via a named const object.
I can see the template being useful for testing the class A -- you want to write the class to work with any value, so that you can change the value in future with confidence that you won't immediately get test failures and have to fix the bugs.
So, you could write the template and test it with lots of different values, even though no "real" program will use more than one instantiation of the template.
Obviously there are other ways to write a class whose behavior depends on an integer value, and test it. For example you could use a macro and have the test harness compile the code multiple times, or you could make MY_CONST an extern value and link the code against different object files containing different values, or you could make A store the value as a data member (even a static data member).
Which ones work for you depends how the class is going to use the value, but since a template parameter is an integer constant expression it's good for most uses that the const int is good for. You can't take a template parameter's address, is the only thing that immediately springs to mind.
I would always remove the global variable. Let's distinguish 2 cases, MY_CONST is either
an implementation detail in which case I would prefer to make it a private constant
class A
{
private:
static int const MY_CONST = 20;
};
or part of the class interface in which case I would prefer to make it a template parameter and provide it as a public member
template<int N>
class A
{
public:
static int const MY_CONST = N;
};
This way, users can not only read but also "write" (at compile-time) to MY_CONST. If users will not want to specify anything but a default value for N, you could provide a default template argument, or give a simple typedef
typedef A<20> DefaultA;

static const in a struct, using constructor

I was looking for a method to initialize a static float inside a structure BUT using the constructor of the struct. In this site there are already solution to initialize the value but I was unable to find a solution that explicitly use the constructor.
The idea is the following:
struct test {
static const float a;
int b;
test(int bb, float a);
};
test::test(int bb, float aa) {
b=bb;
a=aa;
}
int main() {
int bval=2;
float aval=0.25;
struct test aaa(bval, aval);
return 0;
}
How to implement it correctly? Thank you for any advice.
You can't initialise it other than
const float test::a = something;
Outside the class (in a single compilation unit). However, you can do what you wrote and that will set the variable to the value you pass.
If you're wanting to set it only on the first time the constructor is entered, you can (but shouldn't) do something like
test::test(int bb, float aa){
static float _unused = (test::a = aa);
b=bb;
}
But that doesn't initialise it, it just assigns a value to it, and you'll still have to pass the variable to the constructor every time and nothing will be done with it (unless you give it a default value or something). That is a really terrible design though, it's probably better just to have a static function in the class to set the variable.
Static members are not associated with a particular instance, so they will only ever be initialised once. Constructors on the other hand are invoked on a per-instance basis, so it doesn't make sense to do what you're trying to do.
You can, on the other hand, assign a new value to static members in a constructor, as you're doing above, but you still have to actually initialise the static member outside the struct in the normal manner beforehand.
It's worth observing in passing that other languages (e.g. Java) have the concept of a static constructor for exactly this sort of thing - but C++ doesn't.
That said, you might find the following question interesting:
static constructors in C++? I need to initialize private static objects
You can't initialize a static const var inside constructor.
You should initialize at declaration
static const float a = 3.1416f;
Ensure you understand const keyword.
And should be integral.

static const Member Value vs. Member enum : Which Method is Better & Why?

If you want to associate some constant value with a class, here are two ways to accomplish the same goal:
class Foo
{
public:
static const size_t Life = 42;
};
class Bar
{
public:
enum {Life = 42};
};
Syntactically and semantically they appear to be identical from the client's point of view:
size_t fooLife = Foo::Life;
size_t barLife = Bar::Life;
Is there any reason other than just pure style concerns why one would be preferable to another?
The enum hack used to be necessary because many compilers didn't support in-place initialization of the value. Since this is no longer an issue, go for the other option. Modern compilers are also capable of optimizing this constant so that no storage space is required for it.
The only reason for not using the static const variant is if you want to forbid taking the address of the value: you can't take an address of an enum value while you can take the address of a constant (and this would prompt the compiler to reserve space for the value after all, but only if its address is really taken).
Additionally, the taking of the address will yield a link-time error unless the constant is explicitly defined as well. Notice that it can still be initialized at the site of declaration:
struct foo {
static int const bar = 42; // Declaration, initialization.
};
int const foo::bar; // Definition.
They're not identical:
size_t *pLife1 = &Foo::Life;
size_t *pLife2 = &Bar::Life;
One difference is that the enum defines a type that can be used as a method parameter, for example, to get better type checking. Both are treated as compile time constants by the compiler, so they should generate identical code.
static const values are treated as r-values just like enum in 99% of code you'll see. Constant r-values never have memory generated for them. The advantage enum constants is they can't become l-values in that other 1%. The static const values are type safe and allow for floats, c-strings, etc.
The compiler will make Foo::Life an l-value if it has memory associated with it. The usual way to do that is to take its address. e.g. &Foo::Life;
Here is a subtle example where GCC will use the address:
int foo = rand()? Foo::Life: Foo::Everthing;
The compiler generated code uses the addresses of Life and Everything. Worse, this only produces a linker error about the missing addresses for Foo::Life and Foo::Everything. This behavior is completely standard conforming, though obviously undesirable. There are other compiler specific ways that this can happen, and all standard conforming.
Once you have a conforming c++11 compiler the correct code will be
class Foo {
public:
constexpr size_t Life = 42;
};
This is guaranteed to always be an l-value and it's type-safe, the best of both worlds.
Well, if needed, you can take the address of a static const Member Value. You've have to declare a separate member variable of enum type to take the address of it.
Another third solution?
One subtle difference is that the enum must be defined in the header, and visible for all. When you are avoiding dependencies, this is a pain. For example, in a PImpl, adding an enum is somewhat counter-productive:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
enum { Life = 42 } ;
private :
MyImpl * myImpl ;
}
Another third solution would be a variation on the "const static" alternative proposed in the question: Declaring the variable in the header, but defining it in the source:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
static const int Life ;
private :
MyImpl * myImpl ;
}
.
// MyPImpl.cpp
const int MyPImpl::Life = 42 ;
Note that the value of MyPImpl::Life is hidden from the user of MyPImpl (who includes MyPImpl.hpp).
This will enable the MyPimpl author to change the value of "Life" as needed, without needing the MyPImpl user to recompile, as is the overall aim of the PImpl.