Why not static const references on class member variables? - c++

I have a question about static references on class members in C++. It is easy to create a static const member which is a pointer on a non-static member of the same class; like this:
class A {
public:
int x;
private:
static int A::* const ptr_on_x;
};
int A::* const ptr_on_x = &A::x;
Now, I cannot figure out why I cannot write something like that, i.e. make a static const member which is a reference on a non-static member of the same class:
//won't compile
class B {
public:
int x;
private:
static int B::& const ptr_on_x;
};
int B::& const ptr_on_x = B::x;
From the various posts in SO about différences between pointers and references, I don't find any clue. On the contrary, I even read that "references are kind of aliases". So what do I misundertand?
So is it possible to define some variable aliases inside the same class? I admit that with a simple class it doesn't seem very useful; it is a question about the langage itself.
Also I don't know C++0x very much, so does C++0x offers a solution for this?
EDIT
The comment of MarcinŁoś gives me another idea. You can take a function reference, so can I create a class member which is a reference on a class method?

Simply because there is no such type as a reference-to-member, only a pointer-to-member.
From the various posts in SO about différences between pointers and references, I don't find any clue.
A pointer-to-member has little to do with a pointer apart from its (slightly misleading) name, and the fact that, like a pointer, it refers to something else. There was never considered to be a compelling reason to add an analogous type that looked more like a reference.
So is it possible to define some variable aliases inside the same class?
No, there's no sensible way to do that.
Also I don't know C++0x very much, so does C++0x offers a solution for this?
No.

I think the main confusion is that the pointer is simply an offset pointer (it knows where the member is located in relation to the struct), not an absolute pointer, while a reference is always absolute, hence you cannot do the same.

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.

Is there syntax to prevent instances of a class being const?

Let's say that I create a class where the primary use case will have the user always calling methods that modify its members. Or, looking at it another way, creating a class where every method will modify a class member(s).
For example, let's work with this dummy class:
class Foo
{
public:
void setM_1(int);
void setM_2(char);
void setM_3(float);
private:
int m_1;
char m_2;
float m_3;
};
For this Foo class, creating a const instance of it doesn't make sense, since every method is guaranteed to modify a member.
My goal is this: define this class in such a way that const-ly instantiating this class would have no effect. That is to say, a const Foo instance would be able to call every method that a Foo instance can.
I was able to achieve this behavior by marking every method const, declaring all non-const members mutable, and providing a ctor that initialized all members of the class.
So the const-ignorant version of Foo looks like:
class Foo
{
public:
Foo()
{
m_1 = 0;
m_2 = '\0';
m_3 = 0.0f;
}
void setM_1(int) const;
void setM_2(char) const;
void setM_3(float) const;
private:
mutable int m_1;
mutable char m_2;
mutable float m_3;
};
My question is this: is there a more elegant way of doing this?
Or, is this just bad class design? (no debates please).
After Answer Edit:
It's official: I just took a brain crap.
Kerrek SB is right: creating a const Foo and using class-modifying methods would raise compiler errors anyways, so my "const-ignorant" Foo is pointless.
A little documentation would solve my "problem".
No wonder I had a hunch that this was terrible class design.
Excuse me everyone, this question must've been an eyesore. Thank you for the constructive criticism.
Your goal is fundamentally incorrect. const exists not for funsies, but because it means that you really need const. Such a class would break horribly as e.g. a set key- where mutating it would break the ordering. There are other pitfalls like what happens when you provide it as a temporary in certain cases.
If your class cannot be realistically used in a const way, the interface should not lie about it and pretend that it's const when it isn't.
As for your question about bad design, I can safely say that yes, this sounds like a truly terrible design.
No, thank frak.
This makes no sense and would be extremely confusing/dangerous.
If you don't think it makes sense to have a const T then don't instantiate a const T.
From a language point of view, what bad things will happen if a class cannot be const:
First of all, is it that declaring an L-value of type const for it is not allowed, or that const references to it are also prohibited?
If you do not have const reference, then you won't have the default copy constructor, or copy assignment operator. You can't have the class be a member of any other class either, unless that also cannot be const.
I have seen some (sloppy) code where people implement iterators, and because they get tired of writing boilerplate, they implement const_iterators by const_casting away the const and using the non-const iterator implementation. They do this with classes that they know won't "actually" be const, so it won't be undefined behavior in their program. Potentially, not much fun for maintainers though.
For these classes, the class "cannot be const" in the sense that if you actually created a const one on the stack and used it normally you could technically get UB.
If what you want is for the compiler to complain when someone creates a const instance of some class, I think that doesn't really make sense. Const is fundamentally a "promise not to change something". Why would you want to forbid the programmer from making a promise about how he will use something, that seems only beneficial.

Using const getter-style functions in place of static data members

A very simple thought that got me wondering: is there anything to be gained from using the following in a class:
static const int maximum_hp{10};
Rather than
int maximum_hp() const{return 10;};
...?
As far as I can see, the first way makes it easier to override the value of maximum_hp if needed in child classes (by declaring it virtual, of course); static data members cannot be modified, however. For constant primitive types, it seems, to me, to be a better way to go about it.
There is one thing which the static member gives you that the function does not: if the value is present in the class definition like you've shown, it can be used as a constant expression (such as an array bound or a template argument). In other words, this is legal:
std::array<int, Class::maximum_hp_static_memer> a;
while this is not:
std::array<int, c.maximum_hp_function()> a;

Typecasting Member Variable Pointer to Object Pointer

I want to know if typecasting a member variable to object pointer is okay to do in C++?
I have a class as follows -
class Foo
{
private:
int x;
int y;
int z;
public
void func1(...);
void func2(...);
void func3(...);
}
In addition I have a 3rd party code, which has a callback as -
void callbackFunction (int *xPointer)
{
// This is what I want to do
Foo * fooPtr = (Foo*)xPointer;
if(fooPtr->y == fooPtr->z)
{
//... do something
}
}
In this code, the xPointer variable points to int x of my class object.
Now, I want to know can I somehow typecast xPointer to Foo *. In C, I typecasted the pointer to struct pointer to access other member, without any problem.
Is there any danger involving such typecast in case of C++?
If it is a problem, then how can I get pointer to object using the pointer to its member variable?
Thank You
To be able to work directly with class pointers to obtain pointers to their members you must make sure that the class is a POD type. Otherwise there could be hidden members (like a vtable) or paddings that would break any effort.
To know it you should try with std::is_pod<Foo> which is a convenience trait class that will tell you if the class has a standard layout.
In any case it sounds like you should avoid this approach, since it seems inherently unsafe. Why can't you just pass the pointer to the member variable? Eg:
Foo myFoo;
cllabackFunction(&(myFoo.x));
This doesnt entirely strike me as a thing you really want to be doing. Still,
There is the offsetof (type,member) macro, it returns the byte offset of a field within your struct. You can use that to get the base address of the object (from the address of one of its members - if you know which member) and cast that address to the correct type.
of course, its not guaranteed to work for non-PODS, although not guaranteed doesn't mean it wont work, your ok with non-portable and potentially undefined behaviour aren't you?

Arrays of function pointers as members of classes

Can I have, as a private member of a class, an array of function pointers? Something like,
class MyClass {
public: //public stuff
private:
void (*specficFunctions[16]) (void);
}
I specifically don't want to use functors or functionoids.
Yes, though you usually want to use a typedef to keep the syntax a bit more manageable:
class MyClass {
typedef void (*fptr)(void);
fptr SpecificFunctions[16];
};
Note, however, that these are pointers to global functions, not member functions.
There's nothing special about function pointers. The declaration syntax may be confusing (which can be mitigated with typedefs) but they're not really different from any other pointer. If you can make an array of pointers, you can make an array of function pointers. There's also nothing special about a private member of a class compared with any other type of variable. If you can make an array, you can make an array a private member of a class.
Yes. (You can always answer this kind of question by trying to compile such code.)