如何消除模板代码的歧义?

时间:2009-05-08 21:45:52

标签: c++ templates

我无法弄清楚如何解决我遇到的编译器错误。我把它简化为这个最简单的表示法:

enum EAtomId { EAtomId_Test };

int StringFormat(char* o_dest, size_t i_destSizeChars, const char* i_format, ...);

template <size_t SIZE>
int StringFormat(char (&o_dest)[SIZE], EAtomId i_format, ...);

void func()
{
    char textBuffer[1000];
    StringFormat(textBuffer, EAtomId_Test, "hi there");
}

编译错误是:

repro.cpp(17) : error C2666: 'StringFormat' : 2 overloads have similar conversions
    C:\Users\sbilas\Desktop\repro.cpp(9): could be 'int StringFormat(char *,size_t,const char *,...)'
    while trying to match the argument list '(char [1000], EAtomId, const char [9])'

这是完整的错误btw。我有点惊讶它没有列出两个可用的版本..

我遇到这个错误的几个问题。首先,我不明白为什么它含糊不清。编译器不应该看到char(&amp;)[]版本作为匹配的明显案例吗?第二,如何在进行查找时阻止枚举转换为size_t?好像我在这里遇到了一些非常具体的C ++规则。

对我来说最简单的解决方法是将缓冲区大小的size_t放在实际缓冲区的前面。但是这将破坏我们在代码中放入缓冲区然后大小的所有约定。还有另一种方法吗?

这是在VC ++ 2005 btw上,但它在我拥有的其他几个编译器上重现(这是在跨平台游戏中)。

2 个答案:

答案 0 :(得分:2)

您有StringFormat的两个声明:

int StringFormat(char* o_dest, size_t i_destSizeChars,
                 const char* i_format, ...);

template <size_t SIZE>
int StringFormat(char (&o_dest)[SIZE], EAtomId i_format, ...);

当函数模板和普通(非模板)函数都可用时,阅读与参数相关的查找和替换规则。

答案 1 :(得分:2)

上述代码的问题是由普通的重载解析规则引起的,并不是特定于模板的。以下带有两个普通函数的代码仍然显示出歧义:

enum EAtomId { EAtomId_Test };
const int SIZE=1000;

int StringFormat(char * s
  , size_t i_destSizeChars
  , const char* i_format
  , ...);

int StringFormat(char (&a)[SIZE]
  , EAtomId i_format
  , ...);

void func()
{
    char textBuffer[SIZE];
    StringFormat (textBuffer, EAtomId_Test, "hi there");
}

适用的重载决策规则如下(13.3.3):

  • 对于每组参数,计算出发生的转换集
  • 最佳功能是所有转换至少与所有其他重载中的转换一样好的函数。

依次采取以下各项:

功能1:

  1. textBuffer-&gt; s:数组到指针(完全匹配13.3.3.1.1 / 3) - 标识
  2. EAtomId_Test-&gt; i_destSizeChars:可能的推广和积分转换
  3. string literal-&gt; const char *:Array to pointer
  4. 功能2:

    1. textBuffer-&gt; a:身份转换
    2. EAtomId_Test-&gt; EAtomId:身份转换
    3. string literal-&gt;省略号:省略号转换
    4. 依次比较每个转化次数:

      1. 功能1与功能2相同
      2. 功能2优于功能1
      3. 功能1优于功能2
      4. 因此,功能1和功能2对于所有转换都不是最好,因此调用不明确。