'&' : illegal operation on bound member function expression [duplicate] - c++

This question already has answers here:
Print address of virtual member function
(5 answers)
Closed 8 years ago.
This works when I try from a single cpp file with a main function,
sprintf(smem_options ,
"#transcode{vcodec=RV24}:smem{"
"video-prerender-callback=%lld,"
"no-time-sync},"
, (long long int)(intptr_t)(void*)&cbVideoPrerender
);
How do I pass function arguments to sprintf within a class?
sprintf(smem_options ,
"#transcode{vcodec=RV24}:smem{"
"video-prerender-callback=%lld,"
"no-time-sync},"
, (long long int)(intptr_t)(void*)&cbVideoPrerender
);
The error message I get is: error C2276: '&' : illegal operation on bound member function expression

Assuming cbVideoPrerenderer is a member function in the second example, you need to say &Foo::cbVideoPrerenderer where Foo is the class it is a member of.
But that will only be valid if it is a static member function. Non-static member functions are not like normal functions, and when you form a pointer-to-member-function with the &Foo::bar syntax the thing you get back cannot be converted to a void* (it is typically something twice as large as a pointer, as it contains information about the object type).

What you're trying to do is conditionally supported behavior in C++11,
and illegal in earlier versions, in both cases. You can't reliably
convert a pointer to a function (member or otherwise) to a void*.
(I've worked on systems where a pointer to a function was 32 bits, but a
void* only 16.)
In practice, most compilers will (illegally, in pre-C++11) ignore the
error for non-member functions. Posix requires that function
pointers and data pointers be compatible, and they are under Windows as
well. (Today: only of the systems where they weren't for me was an
early Unix.) As for pointers to members: a pointer to a static member
has a type compatible to a pointer to a function (and so will work in
practice, if the compiler allows it), but a pointer to a non-static
member has a completely different type, usually with a different size,
and a different representation. About the only way you can reliably
output one is as a series of byte values: put the address in a properly
typed variable, take the address of that variable, convert it to
unsigned char const*, then use "%02x" to output each byte.
But the real question is why you want to do this. There is nothing that
you can reliably do with the value you output, regardlessly of how you
output it.

Related

Why does this C++ data member declaration contain an ampersand? [duplicate]

This question already has answers here:
how does the ampersand(&) sign work in c++? [duplicate]
(3 answers)
What does '&' do in a C++ declaration?
(7 answers)
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 2 years ago.
I am a novice trying to understand some C++ code in the open-source game Simutrans. Specifically, this declaration (line 79 in this header file):
class env_t
{
public:
<snip>
/// if we are the server, we are at this port
/// #see network_init_server()
static const uint16 &server;
The context tells us this line concerns public data members of the class env_t. The static keyword tells us that all objects of class env_t will have the property server.
Server's type is uint16 (a 16-bit unsigned integer) and it is a constant (so it cannot be overwritten in normal circumstances).
The part that puzzles me is why there is an ampersand (&) at the beginning of the member's name. I have only previously come across the ampersand in bitwise arithmetic and as the "address of" operator. Neither of those uses fit here: there is no arithmetic and I do not see how you could define server as the address of server. Wouldn't that be telling the program that the only possible value of the variable is the variable's own memory address? That not only seems to be circular, but it seems to be inconsistent with the fact that the program can definitely use more than 16 bits of memory addresses for other purposes.
It has been difficult to search for explanations because the ampersand is also a search operator. But this article gives seven different uses of ampersands in C++ and none of them seem to fit here. It's not an expression nor a double ampersand. According to these S.O. answers, the ampersand can be used in a function template to indicate that a parameter must be of a reference type. But my example is declaring a data member, which is not a template, and indeed not any kind of function. And the type is clearly uint16, right? So what does the ampersand indicate here, please?
It should be noted that Simutrans is more than two decades old, before all platforms had the Standard Library, so its code is sometimes idiosyncratic. But I am sure the more relevant fact is that I'm a beginner at C++!
That notation indicates that server is a reference. This has enough similarities to pointers that if you are comfortable with them, you can think of them as a very restricted pointer. If you aren't so comfortable with pointers, a reference is not a variable that holds onto its own data. Rather, it is a reference to another variable. This notation indicates that server is actually referring to data somewhere else, most likely outside of your env_t class.
This is typically done for two reasons. One is that if you change this value, it changes the value of the actual variable being referred to, so that if another piece of code looks at its value, they'll see your change. Vice versa, if someone else changes the value of the variable referenced by server, and you query the value of server, you'll see their changes.

If ampersands aren't needed for function pointers, why does boost::bind require one?

I've always believed that function pointers don't require an ampersand:
Do function pointers need an ampersand
Yet, every example I've seen of using boost::bind shows one, and my compiler - in most situations - gives a typically inscrutable error message if it's omitted.
synchronize(boost::bind(&Device::asyncUpdate , this, "ErrorMessage")); // Works
synchronize(boost::bind(Device::asyncUpdate , this, "ErrorMessage")); // Fails
Am I wrong in assuming that boost::bind's first parameter is basically function pointer?
Function pointers don't need it, member function pointers do.
Device::asyncUpdate is member function, as you could guess because it is being bound to this.
Here's a normative quote from n3337, 5.3.1/4
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses.

Is the *only* purpose of a *function signature* (as opp. to type) to define duplicates in a potential overload set - or are there other purposes?

Related to Why does casting a function to a function type that is identical except for return type fail?, I would like to understand, in a fuller way, the distinction between a function's type and a function's signature.
For example, the type of a function must typically be considered when dealing with function pointers, and the type of the function includes the return type of that function.
However, as noted in Mike Seymour's answer to the above-linked question, the signature of a function is different from the type of a function. The signature is certainly used to disambiguate from among potential overloaded functions (noting that the return type of functions does not play a role in identifying unique functions). But, I would now like to understand the relevance and importance of function signatures vs. function types. It occurs to me that the only purpose of function signatures in C++ is to identify overload candidates and/or unique functions in an overload set, during overload resolution.
Am I correct? Is overload resolution the only purpose of function signatures in C++? Or are there any other uses/applications of function signatures, besides (or only indirectly related to) overload resolution?
ADDENDUM For clarity, please note that I am specifically seeking to understand the distinction between the purpose of a function signature and a function type. I.e., I know that a function type is required both for the use of function pointers, and for a compiler/linker's implementation of a calling convention. However, the calling convention is relevant only after overload resolution is complete. I am here asking, specifically, if the only purpose of the function signature (as opposed to type) is for overload resolution.
Am I correct?
As far as I'm concerned, there are other purposes too. Consider that C also has function signatures but doesn't have overloading.
Apart from overloading, the fundamental purpose of function signatures is conforming to the calling convention of a particular platform.
When a function accepts arguments and returns values, the compiler needs to know the type and the size of the arguments in order to pass them correctly to a function. In general, function arguments are pushed onto the stack (this is not a universal rule though, especially on 64-bit architecture systems). Consider the following situation. If you call a function like
foo(42);
how does the compiler know what is the size of the integer value it has to pass to the function? The number 42 can be represented using various bit width, for example as a 1, 2, 4 (or even 8)-byte integer:
00101010
0000000000101010
00000000000000000000000000101010
Now if the function doesn't have a signature which tells that, for instance, the argument is a char (which is 1 byte), or a short (which may be 2 bytes) or an int, which may be 4 bytes, then the compiler has no way of determining the correct size. It means that if it pushes an arbitrary number of bytes to the stack, but the function expects another size, then stack corruption occurs.
Another good example is returning structures (struct). Usually, primitive return values (such as integers and floating-point numbers) are returned in a register; this is generally the EAX register on x86. But what if one wants to write a function returning a struct? if the overall size of the struct is so large that it doesn't fit into a register, the compiler must generate code that pushes the return value onto the stack as opposed to assigning it to a register. So if a function is defined as
int foo()
{
return 1337;
}
or as
struct bar {
int a;
char b[16];
float x;
};
struct bar foo()
{
struct bar ret;
ret.a = 0;
memcpy(&ret.b, "abcdefghijklmno", sizeof(ret.b));
ret.x = 3.1415927;
return ret;
}
different assembly (and machine code) will be generated - the first function that returns an integer will use the EAX register for storing the return value, but the second call will have to use the stack.
The standard mentions that signatures are used for name mangling and linking.
That being said, name mangling is not standarized. The return type is redundant in a function symbol (since there is only one possible return type for a function with a given name and arguments in a valid program, it is not required to differentiate two different symbols), but even then some ABIs do include the return type of a function in the mangled name, probably as a way of double checking that there is no violation of the rule above.

What are the uses of the type `std::nullptr_t`?

I learned that nullptr, in addition to being convertible to any pointer type (but not to any integral type) also has its own type std::nullptr_t. So it is possible to have a method overload that accepts std::nullptr_t.
Exactly why is such an overload required?
If more than one overload accepts a pointer type, an overload for std::nullptr_t is necessary to accept a nullptr argument. Without the std::nullptr_t overload, it would be ambiguous which pointer overload should be selected when passed nullptr.
Example:
void f(int *intp)
{
// Passed an int pointer
}
void f(char *charp)
{
// Passed a char pointer
}
void f(std::nullptr_t nullp)
{
// Passed a null pointer
}
There are some special cases that comparison with a nullptr_t type is useful to indicate whether an object is valid.
For example, the operator== and operator!= overloads of std::function could only take nullptr_t as the parameter to tell if the function object is empty. For more details you could read this question.
Also, what other type would you give it, that doesn't simply re-introduce the problems we had with NULL? The whole point is to get rid of the nasty implicit conversions, but we can't actually change behaviour of old programs so here we are.
The type was introduced to avoid confusion between integer zero and the the null memory. And as always cpp gives you access to the type. Where as Java only gives you access to the value. It really doesnt matter what purpose you find for it. I normally use it as a token in function overloading.
But I have some issues with the implementation of cpp null const.
Why didnt they just continue with NULL or null? That definition was already being used for that purpose. What about code that already was using nullptr for something else.
Not to mention nullptr is just too long. Annoying to type and ugly to look at most times. 6 characters just to default initialize a variable.
With the introduction of nullptr, you would think zero would no longer be both a integer and null pointer const. However zero still holds that annoying ambiguity. So I dont see the sense then of this new nullptr value. If you define a function that can accept an integer or a char pointer, and pass zero to that function call, the compiler will complain that it is totally ambigious! And I dont think casting to an integer will help.
Finally, it sucks that nullptr_t is part of the std namespace and not simply a keyword. Infact I am just learning this fact, after how long I have been using nullptr_t in my functions. MinGW32 that comes with CodeBlocks allows you to get away with using nullptr_t with std namespace. Infact MinGW32 allows void* increment and a whole lot of other things.
Which leads me to: cpp has too much denominations and confusion. To the point where code compatibility with one compiler is not compatibility with another of the same cpp version. Static library of one compiler cannot work with a different compiler. There is no reason why it has to be this way. And I think this is just one way to help kill cpp.

Disabling "bad function cast" warning

I'm receiving the following warning:
warning: converting from 'void (MyClass::*)(byte)' to 'void (*)(byte)'
This is because I need to pass as argument a member function instead of an ordinary function. But the program is running correctly.
I'd like to disable this warning (Wno-bad-function-cast doesn't work for C++) or to implement a different way to pass a member function.
No. Take this warning seriously. You should rather change your code to handle this scenario.
Pointer to member function(void (MyClass::*)(byte)) and normal function pointer (void (*)(byte)) are entirely different. See this link. You cannot cast them just like that. It results in undefined behavior or crash.
See here, how they are different:
void foo (byte); // normal function
struct MyClass {
void foo (byte); // member function
}
Now you may feel that, foo(byte) and MyClass::foo(byte) have same signature, then why their function pointers are NOT same. It's because, MyClass::foo(byte) is internally resolved somewhat as,
void foo(MyClass* const this, byte);
Now you can smell the difference between them.
Declare pointer to member function as,
void (MyClass::*ptr)(byte) = &MyClass::foo;
You have to use this ptr with the object of MyClass, such as:
MyClass obj;
obj.*ptr('a');
You can't pass a function that takes two arguments to a place that expects a function that takes one. Can't be done, forget about it, period, end of story. The caller passes one argument to your function. It doesn't know about the second argument, it doesn't pass it to your function, you can't make it do what you want however hard you try.
For the very same reason you can't pass a non-static member function where a regular function is expected. A member function needs an object to operate on. Whatever code calls your function doesn't know about the object, there's no way to pass it the object, and there's no way to make it use the right calling sequence that takes the object into account.
Interfaces that take user's functions, without taking additional data that the user might want to pass to his function, are inherently evil. Look at the qsort() function from the C standard library. That's an example of an evil interface. Suppose you want to sort an array of string according to some collation scheme defined externally. But all it accepts is a comparison function that takes two values. How do you pass that collation scheme to your comparison function? You can't, and so if you want it working, you must use an evil global variable, with all the strings attached to it.
That's why C++ has moved away from passing function pointers around, and towards function objects. Function objects can encapsulate whatever data you want.
Also, this may be helpful
union FuncPtr
{
void (* func)(MyClass* ptr, byte);
void (MyClass::* mem_func)(byte);
};