Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pointer to member function of incomplete type

I don't understand why adding a forward declaration for a class changes a size of its pointer to member type

#include <iostream>
using namespace std;

int main()
{
    //struct CL;
    //cout<<sizeof(int (CL::*)())<<endl; 
    struct CL{};
    cout<<sizeof(int (CL::*)())<<endl;
}

output VS2013:
4

But if I uncomment the first two lines in main(), then the output is different:
16
16

So, only a simple adding a forward declaration before a definition of struct CL increases a size of a pointer to member of CL. Why? I know that a size of member function pointer depends by structure of a type (e.g. virtual functions and base classes may increase it), but why can the sizeof operator be applied to a pointer to member of an incomplete type? Or it can't? I have not found it in the Standard

like image 1000
Denis Avatar asked Jun 18 '15 18:06

Denis


People also ask

What is an incomplete type in C?

An incomplete type is a type that describes an identifier but lacks information needed to determine the size of the identifier. An incomplete type can be: A structure type whose members you have not yet specified. A union type whose members you have not yet specified.

Which pointer is automatically passed to a member function when it is called?

When a member function is called, it is automatically passed an implicit argument that is a pointer to the invoking objects. This pointer is known as 'this' pointer.

Why can't the this pointer be used in non member functions?

The this pointer points to the instance data for the object. The interrupt hardware/firmware in the system is not capable of providing the this pointer argument. You must use “normal” functions (non class members) or static member functions as interrupt service routines.

What does incomplete type mean in GDB?

It means that the type of that variable has been incompletely specified. For example: struct hatstand; struct hatstand *foo; GDB knows that foo is a pointer to a hatstand structure, but the members of that structure haven't been defined. Hence, "incomplete type".


1 Answers

The MSVC compiler uses different sizes for pointers to member functions as an optimization. This optimization violates the Standard. Kudos to Igor Tandetnik mentioning reinterpret_cast in a MSDN form post, [expr.reinterpret.cast]p10

A prvalue of type “pointer to member of X of type T1” can be explicitly converted to a prvalue of a different type “pointer to member of Y of type T2” if T1 and T2 are both function types or both object types. The null member pointer value is converted to the null member pointer value of the destination type. The result of this conversion is unspecified, except in the following cases:

  • converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value.

So there's a roundtrip guarantee, this effectively forces conforming implementations to use the same size for all pointer to member function types.


The MSVC optimization is performed if the /vmb switch is set. For the case of single inheritance, the optimised pointer to member function requires only a void*-sized storage, see The Old New Thing: Pointers to member functions are very strange animals.

If you only forward-declare the type CL and then form a pointer-to-member function, the optimization hopefully is deactivated (I could not find any documentation on that, unfortunately). Otherwise, you might get inconsistent sizes before and after the definition of CL.

By the way, you can get inconsistent sizes for enumerations in VS2010, if you forward-declare them without specifying an underlying type and later explicitly define the underlying type for the definition of the enum. This works only with language extensions activated.

like image 149
dyp Avatar answered Sep 30 '22 19:09

dyp