Reference to member function? [duplicate] - c++

This question already has an answer here:
Why doesn't reference-to-member exist in C++?
(1 answer)
Closed 9 years ago.
I recently find out that there is a reference-to-function concept in C++ :).
So as there are pointer-to-function and pointer-to-member-function different types. The question arises. Is there a "reference-to-member-function" concept?
I tried to compile the following code, but GCC 3.4.6 gives an error.
#include <iostream>
using namespace std;
class A {
public:
virtual void Af() const {
cout << "A::Af()" << endl;
}
};
int main() {
typedef void (A::& MemFnc)() const;
MemFnc mf = &A::Af;
A a;
(a.*mf)();
return 0;
}

There is no such a thing called reference to member in C++.
The language specification explicitly says in a note (§8.3.3/3 - 2003) that,
A pointer to member shall not point to a static member of a class (9.4), a member with reference type, or “cv void.” [Note: see also 5.3 and 5.5. The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. There is no “reference-to-member” type in C++.

No, references to member functions are not possible.
In some sense, the result of dereferencing a pointer to a member function could serve as one, but the only thing you can do with that result is to invoke a function call operator on it, per 5.5[expr.mptr.oper]/6. Nothing else is allowed.

There is no reference to member function.

Related

Const has no effect when passing class member by reference in c++ [duplicate]

This question already has answers here:
Why can a const method take a non const reference?
(2 answers)
Closed 2 years ago.
Consider the following code:
#include <iostream>
class ObjectCalculator {
public:
struct Object {
int id = 0;
};
void setObject(Object& object) const {
object.id = 1;
}
Object m_object;
};
int main() {
ObjectCalculator objCalc{};
std::cout << objCalc.m_object.id << std::endl;
objCalc.setObject(objCalc.m_object);
std::cout << objCalc.m_object.id << std::endl;
return 0;
}
I thought this this line should throw an error during compilation since the internal variable is changed via const method setObject:
objCalc.setObject(objCalc.m_object);
but the code compiles with no errors and outputs:
0
1
Could you please clarify why const does not have effect in this case?
const related to the members of the class.
You modifying the method argument, so it can be changed, regardless of const.
const after method applied to the implicit first method argument this, through which all class members accessed.
cppreference
A non-static member function can be declared with a const, volatile,
or const volatile qualifier (this qualifier appears after the
parameter list in the function declaration). Differently cv-qualified
functions have different types and so may overload each other.
In the body of a cv-qualified function, the this pointer is
cv-qualified, e.g. in a const member function, only other const member
functions may be called normally. (A non-const member function may
still be called if const_cast is applied or through an access path
that does not involve this.)
The const qualifier is to tell that the function does not modify this object.
By passing the object to modify as an argument you don't modify this, you modify the object passed as an argument.
If you tried to modify m_object in the function, you would get the error you expected.

can not make sens of this type `void(C::* volatile)(int) const ` used in an example in C++ reference manual [duplicate]

This question already has answers here:
Can somebody explain this C++ typedef?
(4 answers)
Pointer to class data member "::*"
(18 answers)
Closed 3 years ago.
In the C++17 standard draft document, in subsection (6.7.3) "CV-qualifiers" [basic.type.qualifier]:
paragraph 6, there is this sentence:
For a class type C, the type corresponding to the type-id void(C::* volatile)(int) const
has the top-level cv-qualifier volatile.
I have C language background and was randomly reading C++ standard and can't make sens of this, I tried to interpret it as
a volatile function pointer to a function that can be called on const objects and that takes a single int argument and return a ??? ( C type / void I am lost here)
does someone have an explanation ?
I have tried this code
int main()
{
class C
{
public:
typedef void(C:: * volatile X)(int)const ;
void f(int z) const
{cout << z << endl;}
X a = (X)&f; // had to add -fpermissive flag
};
C t;
t.f(5); // works obviously
(t.a)(5); // gives the following compilation message
main.cpp:22:18: warning: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&main()::C::f’ [-fpermissive]
X a = (X)&f;
^
main.cpp:27:12: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘t.main()::C::a (...)’, e.g. ‘(... ->* t.main()::C::a) (...)’
(t.a)(5);
^
changing to what is adviced doesn't work !
thank you for your help
The C::* syntax denotes a member-function pointer which means a pointer to a member-function (sometimes called a method) that belongs to a class C.
In order to obtain an address of a member-function you need to use special syntax with qualified member-function name:
X a = &C::f;
In order to call a member-function via pointer you need to use a special operator .* (as your compiler advises):
(t.*(t.a))(5);
Note that we need to use t twice: for accessing a member and for calling a with t as this.

Overloading type cast operator, to cast to a pointer to function [duplicate]

This question already has answers here:
C++ Conversion operator for converting to function pointer
(6 answers)
Closed 8 years ago.
I'm having some difficulty, overloading the cast to pointer to function operator of a class. In code, what I want is this:
typedef int(*funcptrtype)(int);
struct castable {
operator funcptrtype() {return NULL;}
};
but I want to be able to do it without using the typedef. If you're curious, I need this, because pre-c++11 template aliases aren't available (so the typedef trick is not an option in templated contexts...)
I would normally expect this to work:
operator int(*)(int)() {return NULL;}
But it doesn't. The compiler (g++ 4.6.1) says:
error: ‘<invalid operator>’ declared as function returning a function
This works:
int (* operator()())(int){return 0;}
But you're actually overloading the operator() to return a function pointer :)
The standard says:
The conversion-type-id shall not represent a function type nor an
array type
But it doesn't say function pointer type (The first code snipplet works anyway...).
Does anyone know the right syntax w/o typedef?
The grammar doesn't allow this: the type in a conversion operator declaration is a type-specifier, not a type-id. You have to use a typedef or alias; in a template context, use the usual replacement:
template<typename T>
struct something {
typedef T (*type)(int);
};

Why exactly is this template function successfully compiling? [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Destructors of builtin types (int, char etc..)
Template Function:
template<typename T> void kill(T* type)
{
type->~T();
}
Call:
int x= 5;
kill(&x);
woah, it compiled!? How can a primitive type like int have a destructor? It is also working with char , bool etc.
§12.4.16 of the Standard says
16 [ Note: the notation for explicit call of a destructor can be used for any scalar type
name (5.2.4). Allowing this makes it possible to write code without having to know if a
destructor exists for a given type. For example,
typedef int I;
I* p;
p->I::~I();
—end note ]
The relevant part of the standard is §5.2.4/1:
The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type named by type-name. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix expression before the dot or arrow.

C++ static const access through a NULL pointer [duplicate]

This question already has answers here:
c++ access static members using null pointer
(5 answers)
Closed 8 years ago.
class Foo {
public:
static const int kType = 42;
};
void Func() {
Foo *bar = NULL;
int x = bar->kType;
putc(x, stderr);
}
Is this defined behavior? I read through the C++ standard but couldn't find anything about accessing a static const value like this... I've examined the assembly produced by GCC 4.2, Clang++, and Visual Studio 2010 and none of them perform a dereference of the NULL pointer, but I'd like to be sure.
You can use a pointer (or other expression) to access a static member; however, doing so through a NULL pointer unfortunately is officially undefined behavior. From 9.4/2 "Static members":
A static member s of class X may be
referred to using the qualified-id
expression X::s; it is not necessary
to use the class member access syntax
(5.2.5) to refer to a static member. A
static member may be referred to using
the class member access syntax, in
which case the object-expression is
evaluated.
Based on the example that follows:
class process {
public:
static void reschedule();
};
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
The intent is to allow you to ensure that functions will be called in this scenario.
I believe that the actual value of the type is not used at all when calling
bar->kType
since kType is static, and bar is of type Foo it is the same as calling
Foo::kType
which you should really be doing anyway for clarity.
Calling bar->kType gives a compiler warning on most platforms for this reason.
Apart from the issue about accessing through the NULL pointer, there is another subtle issue in the code
$9.4.2/2 - "The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition."
$9.4.2/4- "If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer."
class Foo {
public:
static const int kType = 42;
};
int const Foo::kType;
void Func() {
Foo *bar = NULL;
int x = bar->kType;
putc(x, stderr);
}
So, yet one more reason for UB in the OP code.
Even if it worked it is awful code.
In serious programming you code not only for yourself, but also for others who will maintain your code.
Playing tricks like this must be avoided, because you respect your colleagues.
One consequence of this code: whether the pointer is NULL or not is even not at question, but it implies that this member kType may not be a plain non-static member of the class. Sometimes classes are big (this is evil too) and one cannot always recheck the definition of each and every variable.
Be rigorous. And call all your static members only this way:
Foo::kType
Another possibility is to follow a coding convention that let know that the member is static, for example, a s_ prefix for all classes static members:
Foo::s_kType
There is a higher rule so to speak which basically says - don't even think about compiling things that are provably not used. Advanced template programming depends on this a lot, so even if it might be a bit gray-zonish when a compiler clearly sees that the result of a construct is not used it's just going to eliminate it. Especially when it's provably safe like in this case.
You may want to try a few variants if you want - like making pointer a param of a function, result of a function, leaving a pointer uninitialized (best chance for triggering compiler complaint), doing a straight cast of 0 (best chance of being conplaint-free).