工作函数如何使用可变参数解析?

时间:2017-07-07 11:02:31

标签: c++ overloading variadic-functions

#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;
}

任何人都可以解释一下这里的功能是如何解决的?  令人惊讶的是那里;

  //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, ...)

那里也很有意思。我所期望的是应该调用没有布尔参数的重载。

2 个答案:

答案 0 :(得分:2)

省略号是重载分辨率的最后手段,如果有更好的匹配,则函数调用将被解析为该匹配。您的函数调用(未注释)都涉及整数文字作为第一个参数。而且,由于您的宏在更换时都是转换为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"的转换以及"abc"与省略号的匹配具有相同的优先级,因此不明确。

供您参考,使用编译时可变参数模板而不是C样式可变参数几乎总是更好。

答案 1 :(得分:1)

正如@Shaggi已经指出的那样。符合标准,

  

在引入nullptr之前,使用零(0)作为符号   空指针。例如:

int* x = 0; // x gets the value nullptr
     

没有为对象分配地址0和0(全零位   pattern)是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, ...)