Casting an object to a reference? - c++

I've been reading some OSS code lately and stumbled upon this peculiar piece:
class Foo { ..... };
void bar() {
Foo x;
Foo *y=new Foo();
x=(const Foo &) *y;
}
For the life of me I can't find documentation about the behavior of casting an object to a const reference.

x=(const Foo &) *y; is assignment. The only reason I see to explicitly cast to const reference is to have Foo::operator=(const Foo &) called for assignment if Foo::operator=(Foo &) also exists.

x=(const Foo &) y; line invokes undefined behavior.
Prefer to avoid C-style casts; they are easy to get wrong. You silence the compiler, so they are too dangerous.
Edit: this answer was relevant at the time, when in the question y was not dereferenced prior to the cast to const Foo &. For the answer to the question after *y edit, please see the answer given by n0rd

Interestingly, the misread code could still be possible, if Foo has a non-explicit constructor that takes a Foo* pointer.
#include <iostream>
class Foo{
public:
Foo() {}
Foo(Foo*) { std::cout << "Aha!\n"; }
};
int main(){
Foo* pf = new Foo;
Foo f = (const Foo&)pf;
std::cin.get();
}
See the output at Ideone.
Interestingly, if you make the constructor explicit, it shows the undefined behaviour explained by #usta.

You'll have to declare x after y:
Foo* y = new Foo();
Foo& x = *y;
Alternatively:
Foo x;
Foo* y = new Foo();
x = (Foo&)*y;

Related

Confusing L-Value and R-Values parentheses

In this example here at the bottom, there are exemplary l-values defined:
// lvalues:
int& foo();
foo() = 42; // ok, foo() is an lvalue
int* p1 = &foo(); // ok, foo() is an lvalue
I am not shure what foo() is here? At first sight it looks like a function/method?
Is int& foo() the same as int& foo; ?
But on the other hand, my compiler says
Error: 'foo' declared as reference but not initialized int & foo;
Same with the rvalues foobar():
// rvalues:
int foobar();
int j = 0;
j = foobar(); // ok, foobar() is an rvalue
int* p2 = &foobar(); // error, cannot take the address of an rvalue
Yes, it is "a function/method", returning a reference to an int. Or, more precisely, this is a declaration of such a function, not definition: it says that such function exists, but does not provide the actual code (because the code is not relevant for the example). Compare how you define functions in header files.
A possible example of code for a similar function:
int a, b;
int& foo(bool which) {
if (which) return a;
else return b;
}
...
foo(true) = 10; // works as a = 10;
Yes, foo is indeed a function. The example is just trying to say "if a function returns an lvalue reference, then the result of calling it is an lvalue."
They probably just mean to say "there is a function foo returning an int& defined." Although technically, the code is correct as-is: it is possible in C++ to declare functions locally:
int main()
{
int foo();
return foo();
}
int foo()
{
return 42;
}
The example is referring to the value category of the function call expression foo(). In this case, foo() is an lvalue because foo returns an int&.

object *operator<<(object* one, type& two);

Original XY Problem Question
I'm in the situation where I need to use the object& operator<<(object& one, type& two); operator overload, with the tweak of using pointers instead of references as below
object *operator<<(object* one, type& two);
The reason is my copy constructors and assignment operators are deleted because I am implementing an object similar to cout and cin. What's a neat hack to do this? I might go with windows API style code where I would define a class pObject; which is a class wrapper for a pointer to the object, but I want to know if there's a more elegant way.
More Generic
I have the following code where T and T' and distinct data types:
// foobar.h
namespace foo {
class bar;
extern foo::bar bExt;
}
foo::bar *operator<<(foo::bar *, T&);
namespace foo {
class bar {
public:
static foo::bar *GetBar() { return new foo::bar; }
void doSomething(T &t) {/* uses member variable mvar.*/}
private:
T' mvar;
friend foo::bar *::operator<<(foo::bar *, T &);
bar() {/*initialize mvar appropriately*/} // default constructor
bar(foo::bar const&) = delete;
void operator=(foo::bar const&) = delete;
};
}
//foobar.cpp
#include "foobar.h"
foo::bar *foo::bExt = GetBar();
foo::bar *operator<<(foo::bar *b, T&)
{
b->doSomething(T);
return b;
}
// main.cpp
#include "foobar.h"
int main()
{
T x = /*something*/;
foo::bExt << x;
}
What I am hoping for is that the user will not be able to create an instance of bar or modify the foo::bExt, which is not a constant because doSomething() modifies it. Finally, I need a way to do it all while still allowing for the operator overload object& operator<<(object& one, type& two); which has been incorrectly used above.
Further Clarification
The code posted below this paragraph will not compile because the copy constructor and assignment operator have been deleted. However, this is the exact format my code requires because one way or the other the extern variable foo::bExt needs to be defined via some complicated constructor procedure and then used as an argument to the overload operator similar to the appearance and use of std::cout. The quick workaround is to to define a extern foo::bar * object, as has been stated in the code above this paragraph, and use the pointer as the argument to the operator. A quick fix is is to dereference the now pointer extern object *foo::bExt every time the operator<< is invoked with it as argument, but no one does *std::cout << 1; so nor should they *foo::bExt << 1;. It seems cumbersome and inelegant, and at least warrants an investigation for an alternative. Hence my question. Don't just take my word for it, try the below code with
g++ -std=c++11 <name>.cpp -o <name>
#include <iostream>
namespace foo
{
class bar;
extern foo::bar bExt;
}
foo::bar &operator<<(foo::bar& ,int&);
namespace foo
{
class bar
{
public:
static foo::bar GetBar()
{
static foo::bar temp;
return temp;
}
void print() {std::cout << v << std::endl;}
private:
int v;
bar() : v(1965) {};
friend foo::bar &::operator<<(foo::bar &, int&);
/* Commenting out the below copy constructor and
* assignment operator allows the code to compile.
*/
bar(foo::bar const&) = delete;
void operator=(foo::bar const&) = delete;
};
foo::bar bExt = foo::bar::GetBar();
}
foo::bar &operator<<(foo::bar &b, int &i)
{
b.v += i;
return b;
}
int main()
{
int i = 50;
foo::bExt << i;
foo::bExt.print();
}
As has been pointed out (no pun intended) in comments on your question, there is nothing wrong with using references; however, it appears that you don't understand why, so I will explain it.
References contain built-in constant pointers. This means that when you pass a reference to an object, neither the copy constructor nor the assignment operator are called on your object; rather, it is the reference's internal pointer that is copied over, and there is still only one copy of the object itself. For that reason, you can still use references to the object, even if the copy constructor and/or assignment operator are deleted.
I hope this helps you understand how references work.
EDIT: actual full solution
Here is an actual solution based on the second code block given in the question:
#include <iostream>
namespace foo
{
class bar;
extern foo::bar& bExt;
}
foo::bar &operator<<(foo::bar& ,int&);
namespace foo
{
class bar
{
public:
static foo::bar* GetBar()
{
return new foo::bar();
}
void print() {std::cout << v << std::endl;}
private:
int v;
bar() : v(1965) {};
friend foo::bar&::operator<<(foo::bar&, int&);
/* Commenting out the below copy constructor and
* assignment operator allows the code to compile.
*/
bar(foo::bar const&) = delete;
void operator=(foo::bar const&) = delete;
};
foo::bar& bExt = *foo::bar::GetBar();
}
foo::bar &operator<<(foo::bar &b, int &i)
{
b.v += i;
return b;
}
int main()
{
int i = 50;
foo::bExt << i;
foo::bExt.print();
}
Hopefully this helps.
Turns out the following overload does the trick:
object *& operator<<(object *& one, type& two);

When is it ok to modify a value when you remove const with const_cast?

According to §7.1.​5.1/4:
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.
So my question becomes: when is an object a const object?
In particular, is a const member in a non-const object considered a const object?
class Foo {
const Bar bar;
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
}
This comes up because I have an immutable class (all fields are const), but I want to have a move constructor, which technically modifies the value passed in. I'm ok with "cheating" in that case, since it doesn't break logical constness.
The simple rule is: it is ok to cast away constness if the original object is not const. So if you have a non-cont object and, say, you pass the const reference to it to a function, it is legal to cast away constness in the function.
In your example the original object is const, so casting constness away is undefined behaviour.
Let us make this a full example:
struct Bar { int x; };
struct Foo {
const Bar bar;
Foo( int x ):bar(x) {}
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
};
now, let us break the world.
int main() {
Foo f(3);
Bar b = {2};
f.replaceBar(b);
std::cout << f.bar.x << "\n";
}
the above can and probably should output 3, because a const object Bar was created with x=3. The compiler can, and should, assume that the const object will be unchanged throughout its lifetime.
Let's break the world more:
struct Bar {
int* x;
Bar(int * p):x(p) {}
~Bar(){ if (x) delete x; }
Bar(Bar&& o):x(o.x){o.x=nullptr;}
Bar& operator=(Bar&& o){
if (x) delete x;
x = o.x;
o.x = nullptr;
}
Bar(Bar const&)=delete;
Bar& operator=(Bar const&)=delete;
};
struct Foo {
const Bar bar;
Foo( int* x ):bar(x) {}
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
};
now the same game can result in the compiler deleting something twice.
int main() {
int* p1 = new int(3);
Foo f( p1 );
Bar b( new int(2) );
f.replaceBar(std::move(b));
}
and the compiler will delete p1 once within replaceBar, and should delete it also at the end of main. It can do this, because you guaranteed that f.bar.x would remain unchanged (const) until the end of its scope, then you violated that promise in replaceBar.
Now, this is just things the compiler has reason to do: the compiler can literally do anything once you have modified an object that was declared const, as you have invoked undefined behavior. Nasal demons, time travel -- anything is up for grabs.
Compilers use the fact that some behavior is undefined (aka, not allowed) to optimize.

Modifying constant object

I was looking through the interview questions to a junior C++ developer position. The question is (quote):
Is the following code correct?
struct Foo
{
int i;
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
};
I would answer:
The code itself is valid according to the C++03 and c++11 standards and will compile successfully.
But it may invoke an undefined behavior during assignment pointer->i
= 0; if the instance of the class on which foo() is being called is declared as const.
I mean that following code will compile successfully and result in undefined behaviour.
struct Foo
{
int i;
Foo ( void )
{
}
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
};
int main ( void )
{
Foo foo1;
foo1.foo(); // Ok
const Foo foo2;
foo2.foo(); // UB
return 0;
}
Is my answer correct or I am missing something? Thank you.
I would first ask what is meant by their ambiguous definition of "correct". You need to know the specification of the program and its intended behaviour.
As you said, if they're just asking if it compiles then the answer is 'yes'. However, if they determine correct to be safe to do, then you can discuss the facts that you state in your question.
By answering this way, the person interviewing can see how that you're analysing what you're being asked, rather than jumping straight into answering, which in my opinion is a good thing to do.
This code may be legally correct, but I guess, the aim of the question is to determine, whether you understood the concept of const itself. Because, on the semantic level, you have a function taking an implicit const object pointer, which it then goes to modify, which is almost certainly a bug.
There are cases, where this may be desired (because the modification is some caching of return values, or similar operation that does not change the semantic value of the object), you would use the mutable keyword for the variable in question.
cheating complier will take the consequences.
struct Foo
{
int i;
Foo(int a):i(a){}
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
bool operator<(const Foo& rhs) const{
return i<rhs.i;
}
};
#include <map>
int main ( void )
{
std::map<Foo,int> kk;
for(int i=0;i<10;++i){
kk.insert(std::make_pair(Foo(i),i));
}
std::map<Foo,int>::iterator ite = kk.find(Foo(4));
const Foo& foo4 = ite->first;
foo4.foo();
ite = kk.find(Foo(4));
const Foo& tmp = ite->first; // crack
return 0;
}
program will crack at "const Foo& tmp = ite->first;"

Can I avoid accidental construction of a temporary? [duplicate]

For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi"); expands to class Foo("hi");, which is ill-formed; but Foo a("hi") expands to class Foo a("hi"), which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.