如何使用可变参数解析工作函数重载?
#define FALSE 0
#define TRUE 1
#define IDS_MYSTR 123
void FnVariadic(const long nIDS, ...)
{
std::cout << "WITHOUT option IDS" << std::endl;
}
void FnVariadic(const bool bOption, const long nIDS, ...)
{
std::cout << "WITH option IDS" << std::endl;
}
void FnVariadic(const char *pStr, ...)
{
std::cout << "WITHOUT option STR" << std::endl;
}
void FnVariadic(const bool bOption, const char *pStr, ...)
{
std::cout << "WITH option STR" << std::endl;
}
int main()
{
FnVariadic(FALSE, IDS_MYSTR, "abc");
//FnVariadic(IDS_MYSTR, FALSE, "abc"); //???
FnVariadic(TRUE, IDS_MYSTR, "abc");
FnVariadic(IDS_MYSTR, TRUE, "abc"); //???
FnVariadic(FALSE, "abc%s", "abc");
//FnVariadic("abc%d%s", FALSE, "abc");
FnVariadic(TRUE, "abc%s", "abc");
//FnVariadic("abc%d%s", TRUE, "abc");
system("pause");
return 0;
}
有人可以解释一下这里怎么工作funtion超载解析? 令人惊讶的是,如何使用可变参数解析工作函数重载?
//FnVariadic(IDS_MYSTR, FALSE, "abc"); //???
FnVariadic(IDS_MYSTR, TRUE, "abc"); //???
第二个编译但不是第一个编译。
(注释行的意思是不编译)
我使用VS2017,似乎;
首先3个电话使用void FnVariadic(const bool bOption, const long nIDS, ...)
和最后2个呼叫使用void FnVariadic(const bool bOption, const char *pStr, ...)
它也intresting那里。我期望的是应该调用没有布尔参数的重载。
在重载分辨率中,省略号是最后的手段,如果有更好的匹配,则函数调用将被解析为匹配。你的函数调用(非注释)都包含一个整数字面量作为第一个参数。而且,由于您的宏,当更换是转换到bool
所有可行的候选人,你有两个候选人
void FnVariadic(const bool bOption, const long nIDS, ...)
void FnVariadic(const bool bOption, const char *pStr, ...)
然后在前三您提供整型常量作为第二个参数。因此,上述两者之间的第一次重载被称为。在最后2中,您提供了字符串文字(可减少到const char*
),因此第二次重载被称为上述两者之间。
至于为何注释行不进行编译
// FnVariadic(IDS_MYSTR, FALSE, "abc"); //???
这不会编译,因为第二个参数是模糊的,一个0
具有特殊的意义不幸的是,它可以解决这两个一const char*
以及作为const long
// FnVariadic("abc%d%s", FALSE, "abc");
同样为这一项,FALSE
是模糊
// FnVariadic("abc%d%s", TRUE, "abc");
这里转化为bool
为"abc%d%s"
和到椭圆匹配具有相同的优先级,并且因此它是不明确的。
供您参考,它几乎总是最好使用对C风格variadics编译时可变参数模板。
是否可以停用这种隐式的0 - > ptr转换?我的意思是可以防止0作为ptr代表?用编译器选项也许? –
@YusufR.Karagöz号GCC对此有警告,但在许多情况下,语言没有进行这种转换就会中断。如果您对解决方案感兴趣,那么重构代码非常容易,因此它可以正常工作(例如,使用SFINAE)。 – Shaggi
正如@Shaggi已经指出的那样。按照标准,
在引入nullptr之前,将零(0)用作 空指针的标记。例如:
int* x = 0; // x gets the value nullptr
无对象与地址0分配,并且0(全零位 图案)是nullptr最常见的代表。零(0)是一个 int。但是,标准的转换(§10.5.2.3)允许0使用 作为指针或指针到成员类型
FnVariadic(IDS_MYSTR, FALSE, "abc");
^~~~const char * OR const long. This is ambiguous.
的常数作为你有两个
void FnVariadic(const bool bOption, const long nIDS, ...)
void FnVariadic(const bool bOption, const char *pStr, ...)
您的问题FALSE是#define'd,因为0等于空指针常量,因此解析在long和const char *重载之间是不明确的。这种情况只存在于字面常量0,这就是为什么设计nullptr的原因(但正如你所看到的,问题仍然存在于语言中)。 – Shaggi
为什么你需要用宏定义'true'和'false'?这些布尔常量是在语言时代之前建立起来的。 – AndyG
@AndyG我们正在使用mfc/atl。这些代码已被写入,没有布尔真/假。这些定义已被使用。但我想了解超负荷解决。不寻找解决方案。 –