C++ vararg function pointer
Does the following result in well-defined behavior? That is, if you cast a non-vararg function f as a vararg function g and call g with the arguments that f expects, does the behavior match that of calling f with those arguments?
class Base {};
class Derived1 : public Base {
public:
int getInt1() {return 1;}
};
class Derived2 : public Base {
public:
int getInt2() {return 2;}
};
typedef int (*vfunc)(...);
int foo (vfunc f) {
Derived1 d1;
Derived2 d2;
return f(&d1, &d2);
}
int bar (Derived1 * p1, Derived2 * p2) {
return p1->getInt1() + p2->getInt2();
}
int main (int argc, char ** argv) {
return foo((vfunc)bar); // Is this program guaranteed to return 3?
}
UPDATE
Is there some way I can get the program to be well-defined, even if using proprietary keywords? Such as doing some stuff like __cdecl
mentioned here:
http://msdn.microsoft.com/en-us/library/984x0h58%28v=vs.80%29.aspx
My end goal is to have a matcher
function that tries matc开发者_如何学JAVAhing on a list of X pointers. The matcher function takes in a predicate (not necessarily a function... might be a list) and takes in a function that it will pass the matched results to. The callback function passed to it takes the same argument types and arity as the predicate matched.
No, the behavior is undefined, per C++11 5.2.11/6 (reinterpret_cast
):
The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined.
The type of bar
is int(Derived1*, Derived2*)
. The type of the function pointed to by f
(the expression through which the call is made) is int(...)
. The two are not the same and therefore the behavior is undefined.
I'm pretty sure the answer is "No."
For instance, in Visual C++, a variadic function will have a different calling convention than a normal function (when using /Gz
).
The calling convention determines what pre-call and post-call assembly code is generated, and you cannot safely mix the two.
精彩评论