C++可变参数函数指针
以下是否会产生明确的行为?也就是说,如果将非可变参数函数 f 转换为可变参数函数 g 并使用 f 期望的参数调用 g,则其行为是否与使用这些参数调用 f 的行为相匹配?
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?
}
更新
有什么方法可以让程序得到明确的定义,即使使用专有关键字也是如此?例如做一些类似这里提到的 __cdecl 的事情:
http://msdn.microsoft.com/en-us/library/984x0h58%28v=vs.80%29.aspx
我的最终目标是拥有一个尝试匹配 X 指针列表的 matcher
函数。匹配器函数接受一个谓词(不一定是一个函数......可能是一个列表)并接受一个将匹配结果传递给的函数。传递给它的回调函数采用与匹配的谓词相同的参数类型和数量。
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 matching 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
否,根据 C++11 5.2.11/6 (
reinterpret_cast
),该行为未定义:bar
的类型为int(Derived1*, Derived2*)
。f
(进行调用的表达式)指向的函数类型是int(...)
。两者不同,因此行为未定义。No, the behavior is undefined, per C++11 5.2.11/6 (
reinterpret_cast
):The type of
bar
isint(Derived1*, Derived2*)
. The type of the function pointed to byf
(the expression through which the call is made) isint(...)
. The two are not the same and therefore the behavior is undefined.我很确定答案是“不”。
例如,在 Visual C++ 中,可变参数函数将具有与普通函数不同的调用约定(使用
/Gz
时)。调用约定决定了生成什么预调用和后调用汇编代码,并且您不能安全地混合这两者。
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.