How can you modify an object without calling member functions? - c++

At 3.10/10, the standard says:
An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances. [Example: a member function called for an object (9.3) can modify the object. ]
So, rvalues are non-modifiable except under certain circumstances. We're told that calling a member function is one of those exceptions. This gives the idea that there are ways of modifying objects other than calling a member function. I can't think of a way.
How can one modify an object without calling a member function?

How can one modify an object [that's specified by an rvalue expression] without calling a member function?
I know of only one way to do that, namely to bind the object to a reference to const, and then cast away the const-ness.
E.g.
template< class Type >
Type& tempRef( Type const& o ) { return const_cast< Type& >( o ); }
struct S { int x; };
int main()
{ tempRef( S() ).x = 3; }
This is because a temporary object is not const itself unless it is of const type, so the example above does not cast away original const-ness (which would be UB).
EDIT, added: Luc Danton’s answer showed another (non-general) way, namely where the temporary's construction stores some reference or pointer to the object in some accessible location.
Cheers & hth.,

This seems to be accepted:
struct T {
int x;
};
int main() {
T().x = 3;
}
I am slightly surprised that this works, because IIRC the LHS of op= must be an lvalue, yet the following implies that even T().x is an rvalue:
struct T {
int x;
};
void f(int& x) {
x = 3;
}
int main() {
f(T().x);
}
Edit: As of 4.6, GCC does warn about T().x = 3: error: using temporary as lvalue.
I can't think of any other way to modify a class object other than through data member access or member function calls. So, I'm going to say... you can't.

Modifying a temporary and not through an lvalue to that temporary:
#include <cstring>
class standard_layout {
standard_layout();
int stuff;
};
standard_layout* global;
standard_layout::standard_layout()
{ global = this; }
void
modify(int)
{
std::memset(global, 0, sizeof *global);
}
int
main()
{
modify( (standard_layout {}, 0) );
}
I don't think it's correct to assume that rvalues of class types are non-modifiable. I now understand that paragraph as 'for non-class types, an lvalue for an object is needed in order to modify that object'.

I can think of one way:
If your class exposes public member variables, you can assign directly to those member variables. For example:
class A
{
public:
int _my_var;
...
};
int main(int argc, char** argv)
{
A *a = new C();
a->_my_var = 10;
}
This is not a good programming style though - exposing a member variable as public isn't something I would advocate or even suggest.
Also, if you can do something really weird, such as directly writing some address in memory, an offset from the pointer to the class object - but why would you do that?

How can one modify an object without calling a member function?
By assigning a value to one of the object's visible data members, of course.

Doing an implicit cast is sort of like calling a member function -- also modifying rvalue refs seems to work.
Tested the following in vc++10 and g++ 4.4.
struct b { int i; b(int x) : i(x) {} };
struct a { int i; a() : i(0) { } operator b() { return i++ /* this works */, b(i); } };
a f(a&& x) { return x.i++ /* this works */, x; }
int main() { b b = f(a()); /* implicit operator b() cast; b.i will equal 2 */ }

A member function can change the member directly, but it can also delegate that responsibility:
struct Foo {
int x;
void Bar() { scanf("%d", &x); }
};
The current wording of the standard has the advantage that one doesn't need to argue whether this is a case of Bar changing the object. If we'd agree that scanf changes the object, then that's just another example.

Related

c++ Why is it legal to call non-const function on member pointer from const function? [duplicate]

A co-worker asked about some code like this that originally had templates in it.
I have removed the templates, but the core question remains: why does this compile OK?
#include <iostream>
class X
{
public:
void foo() { std::cout << "Here\n"; }
};
typedef void (X::*XFUNC)() ;
class CX
{
public:
explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}
void execute() const { (object.*F)(); }
private:
X& object;
XFUNC F;
};
int main(int argc, char* argv[])
{
X x;
const CX cx(x,&X::foo);
cx.execute();
return 0;
}
Given that CX is a const object, and its member function execute is const, therefore inside CX::execute the this pointer is const.
But I am able to call a non-const member function through a member function pointer.
Are member function pointers a documented hole in the const-ness of the world?
What (presumably obvious to others) issue have we missed?
The constness of execute() only affects the this pointer of the class. It makes the type of this a const T* instead of just T*. This is not a 'deep' const though - it only means the members themselves cannot be changed, but anything they point to or reference still can. Your object member already cannot be changed, because references cannot be re-seated to point to anything else. Similarly, you're not changing the F member, just dereferencing it as a member function pointer. So this is all allowed, and OK.
The fact that you make your instance of CX const doesn't change anything: again, that refers to the immediate members not being allowed to be modified, but again anything they point to still can. You can still call const member functions on const objects so no change there.
To illustrate:
class MyClass
{
public:
/* ... */
int* p;
void f() const
{
// member p becomes: int* const p
*p = 5; // not changing p itself, only the thing it points to - allowed
p = NULL; // changing content of p in const function - not allowed
}
};
In this context object is a reference to a X, not a reference to a const X. The const qualifier would be applied to the member (i.e. the reference, but references can't be const), not to the referenced object.
If you change your class definition to not using a reference:
// ...
private:
X object;
// ...
you get the error you are expecting.
The instance object of class X is not const. It is merely referenced by an object which is const. Const-ness recursively applies to subobjects, not to referenced objects.
By the alternative logic, a const method wouldn't be able to modify anything. That is called a "pure function," a concept which doesn't exist in current standard C++.
You are calling foo on object, not on this.
Since object is declared as an X&, in a constant CX, it is actually an X& const (which is not the same as const X&) allowing you to call non const methods on it.
One helpful way of thinking about it might be that your X object is not a member of CX at all.

C++: Casting Member Function Pointer

In the following program, How do I typecast bar to foo?
#include <iostream>
namespace NA {
class A {
public:
int (*foo)(int);
};
}
namespace NB {
class B : public NA::A {
public:
int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
B() {
this->foo = bar; // how to type cast this fn pointer?
}
};
}
int main() {
NA::A *a = new NB::B();
std::cout << a->foo(2) << std::endl;
}
I tried typecasting as follows but something is going terribly wrong when I run the program:
B() {
typedef int (*TypeFoo)(int);
this->foo = reinterpret_cast<TypeFoo> (&bar);
}
Here's the result when I run:
$ ./a.out
31947824
63895648
I was expecting 2 and 4. How does one typecast the member function pointers above?
Update:
After seeing responses indicating there's no solution to the above problem, I am updating this question further with the specific problem I was trying to address.
Please see https://boringssl.googlesource.com/boringssl/+/HEAD/include/openssl/ssl.h#1173 -- I am trying to have different instances of the struct ssl_private_key_method_st operate on different private keys. I was trying to have another struct inherit from ssl_private_key_method_st and have the sign/decrypt/complete methods operate on instance variables of the inherited struct.
I am aware of using SSL_[sg]et_ex_data to pass data to these functions indirectly, but I was looking for a more simpler / direct way of passing instance data to these functions if possible.
You are running into undefined behavior.
TypeFoo and bar are different types of function pointers (int (*)(int) and int (NB::B::*)(int) respectively).
While it is possible to cast one to the other, using the result to call the function will result in undefined behavior.
8.2.10 Reinterpret cast [expr.reinterpret.cast]
...
6. A function pointer can be explicitly converted to a function pointer of a different type. [ Note: The effect of calling a function through a pointer to a function type (11.3.5) that is not the same as the type used in the definition of the function is undefined. —end note ] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. [ Note: See also 7.11 for more
details of pointer conversions. —end note ]
Short answer: you don't.
Non-static member function pointers are weird. Calling one involves a secret this parameter, and they may or may not be virtual. This makes them impossible to mix with ordinary function pointers.
You should consider using std::function<int(int)> instead of int (*)(int). This would allow you to store something like the following lambda:
B(){
std::function<int(int)> myfn = [this](int x){
return bar(x);
};
}
This lambda captures the current object by reference, and this reference is stored inside the std::function object itself. But you can just as well assign any other function to a std::function, directly or through a lambda or bind expression.
On the other hand, if your bar method doesn't really doesn't depend on an instance, just make it static. This will allow it to mix with regular function pointers, since it no longer needs a secret this and cannot be virtual.
static int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
Written like this, &B::bar can be assigned to a regular int (*)(int) function pointer.
Your TypeFoo defines a pointer to a regular function while bar is a method. Each non-static method has an implicit first parameter this.
So you should decide what do you need: a regular function (in this case make the bar static) or a method, in this case you should typedef like that:
typedef int (B::*TypeFoo)(int);
The reinterpret_cast is an error prone practice. If you cannot cast without it - there is high probability that your code is not correct.
Invoking a member function pointer is a real pain. I suggest you go about this the following way, simplifying much of the context handling:
#include <iostream>
namespace NA {
class A {
public:
int (A::*foo)(int);
};
}
namespace NB {
class B : public NA::A {
public:
int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
int callFoo(int x) {
return (this->*foo)(x);
}
B() {
this->foo = (int(A::*)(int)) (&B::bar);
}
};
}
int main() {
NA::A *a = new NB::B();
std::cout << ((NB::B*)a)->callFoo(2) << std::endl;
}

Calls to non static member functions have a hidden parameter that is accessible in the definition of the member function as *this

Can somebody explain this:
Calls to non static member functions have a hidden parameter that is accessible in the definition of the member function as *this. For a member function of myClass, the hidden parameter is usually of type MyClass& (for non const member). This is somewhat surprising given that this has a pointer type. It would have been nicer to make this equivalent to what is now *this. However, this was part of an early version of C++ before reference types were part of the language, and by the time reference types were added, too much code already depended on this being a pointer
Thank you!
This example:
class C
{
public:
int i;
void f(int j) { i = j; }
};
...
C c;
c.f(1);
Is interpreted somewhat (not exactly) like this by the compiler:
class C
{
public:
int i;
};
void C_f(C *this, int j) { this->i = j; }
...
C c;
C_f(&c, 1);
That's all. The methods are separated from the variable data in the object.
The rest of the text just says why a pointer is used, instead of a reference C &p.
Something like this would be possible too:
class C
{
public:
int i;
};
void C_f(C &this, int j) { this.i = j; }
...
C c;
C_f(c, 1);
IOW using a reference instead of a pointer => no manual work with addresses etc.
But as it is, this is only the address/pointer of the object. Because of historical reasons.

Why does C++ allow unnamed function parameters?

The following is a perfectly legal C++ code
void foo (int) {
cout << "Yo!" << endl;
}
int main (int argc, char const *argv[]) {
foo(5);
return 0;
}
I wonder, if there a value to ever leave unnamed parameters in functions, given the fact that they can't be referenced from within the function.
Why is this legal to begin with?
Yes, this is legal. This is useful for implementations of virtuals from the base class in implementations that do not intend on using the corresponding parameter: you must declare the parameter to match the signature of the virtual function in the base class, but you are not planning to use it, so you do not specify the name.
The other common case is when you provide a callback to some library, and you must conform to a signature that the library has established (thanks, Aasmund Eldhuset for bringing this up).
There is also a special case for defining your own post-increment and post-decrement operators: they must have a signature with an int parameter, but that parameter is always unused. This convention is bordering on a hack in the language design, though.
Of course not naming a parameter is legal when just declaring the function, but it's also legal in the implementation. This last apparently strange version is useful when the function needs to declare the parameter to have a specific fixed signature, but the parameter is not needed.
This may happen for example for a method in a derived class, for a callback function or for a template parameter.
Not giving the parameter a name makes clear that the parameter is not needed and its value will not be used. Some compilers if you instead name a parameter and then simply don't use it will emit a warning that possibly there is a problem with the function body.
Just wanted to mention a specific (unusual but interesting) usecase - the "passkey idiom".
It uses a "dummy" parameter of a type, constructor of which is accessible only to its friends. Its purpose is only to check, whether the caller has access to this constructor. So it needs no name as it is not used in the function, only the compiler uses it.
It's used like this:
class Friendly; // Just a forward declaration
class Key {
private:
Key() {}
friend class Friendly;
};
class Safe() {
public:
static int locked(Key, int i) {
// Do something with `i`,
// but the key is never used.
return i;
}
private:
static void inaccessible() {}
};
class Friendly {
public:
void foo() {
int i = Safe::locked(Key(), 1); // OK
int j = Safe::locked({}, 2); // OK, sice C++11
}
void bar() {
Safe::inaccessible(); // Not OK, its inaccessible
}
};
int i = Safe::locked(3); // Not OK, wrong parameters
int j = Safe::locked(Key(), 4); // Not OK, `Key` constructor is inaccessible
int k = Safe::locked({}, 5); // Not OK, `{}` means `Key()` implicitly
I just want to add that there is sometimes a difference whether you name a parameter or not. For example, the compiler treats a named rvalue reference as an lvalue and an unnamed rvalue reference as an rvalue.
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return block;
}
int main()
{
g(f(MemoryBlock()));
}
This example produces the following output:
In g(const MemoryBlock&).
In g(MemoryBlock&&).
In this example, the main function passes an rvalue to f. The body of f treats its named parameter as an lvalue. The call from f to g binds the parameter to an lvalue reference (the first overloaded version of g).

Why can I call a non-const member function pointer from a const method?

A co-worker asked about some code like this that originally had templates in it.
I have removed the templates, but the core question remains: why does this compile OK?
#include <iostream>
class X
{
public:
void foo() { std::cout << "Here\n"; }
};
typedef void (X::*XFUNC)() ;
class CX
{
public:
explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}
void execute() const { (object.*F)(); }
private:
X& object;
XFUNC F;
};
int main(int argc, char* argv[])
{
X x;
const CX cx(x,&X::foo);
cx.execute();
return 0;
}
Given that CX is a const object, and its member function execute is const, therefore inside CX::execute the this pointer is const.
But I am able to call a non-const member function through a member function pointer.
Are member function pointers a documented hole in the const-ness of the world?
What (presumably obvious to others) issue have we missed?
The constness of execute() only affects the this pointer of the class. It makes the type of this a const T* instead of just T*. This is not a 'deep' const though - it only means the members themselves cannot be changed, but anything they point to or reference still can. Your object member already cannot be changed, because references cannot be re-seated to point to anything else. Similarly, you're not changing the F member, just dereferencing it as a member function pointer. So this is all allowed, and OK.
The fact that you make your instance of CX const doesn't change anything: again, that refers to the immediate members not being allowed to be modified, but again anything they point to still can. You can still call const member functions on const objects so no change there.
To illustrate:
class MyClass
{
public:
/* ... */
int* p;
void f() const
{
// member p becomes: int* const p
*p = 5; // not changing p itself, only the thing it points to - allowed
p = NULL; // changing content of p in const function - not allowed
}
};
In this context object is a reference to a X, not a reference to a const X. The const qualifier would be applied to the member (i.e. the reference, but references can't be const), not to the referenced object.
If you change your class definition to not using a reference:
// ...
private:
X object;
// ...
you get the error you are expecting.
The instance object of class X is not const. It is merely referenced by an object which is const. Const-ness recursively applies to subobjects, not to referenced objects.
By the alternative logic, a const method wouldn't be able to modify anything. That is called a "pure function," a concept which doesn't exist in current standard C++.
You are calling foo on object, not on this.
Since object is declared as an X&, in a constant CX, it is actually an X& const (which is not the same as const X&) allowing you to call non const methods on it.
One helpful way of thinking about it might be that your X object is not a member of CX at all.