Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何消除此模板代码的歧义?_C++_Templates - Fatal编程技术网

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

C++ 如何消除此模板代码的歧义?,c++,templates,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, ...); v

我很难想出如何解决遇到的编译器错误。我将其简化为以下最简单的案例表示:

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");
}
顺便说一句,这是全部错误。我有点惊讶它没有列出两个可用版本

我对这个错误有几个问题。首先,我不明白为什么它是模棱两可的。编译器不应该将char&[]版本视为明显的匹配情况吗?第二,如何防止枚举在执行查找时转换为大小?好像我在这里遇到了一些非常特别的C++规则。 对我来说,最简单的解决方法是将缓冲区大小的大小放在实际缓冲区的前面。但这将打破我们在代码中加入缓冲区和大小的所有惯例。还有别的办法吗


这是在VC++2005上的,顺便说一句,但它在我的另外两个编译器上复制。这是在一个跨平台游戏中。

您有两个StringFormat声明:


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

StringFormat有两个声明:


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

上述代码的问题是由于普通重载解析规则造成的,而不是特定于模板的。以下带有两个普通函数的代码仍然显示模糊性:

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:

textBuffer->s:数组到指针的精确匹配13.3.3.1.1/3-标识 EAtomId_测试->i_destSizeChars:可能的升级和积分转换 字符串文字->常量字符*:指向指针的数组 职能2:

textBuffer->a:标识转换 EAtomId_测试->EAtomId:标识转换 字符串文字->省略号:省略号转换 依次比较这些转换,您可以:

功能1与功能2相同 功能2优于功能1 功能1优于功能2
因此,函数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:

textBuffer->s:数组到指针的精确匹配13.3.3.1.1/3-标识 EAtomId_测试->i_destSizeChars:可能的升级和积分转换 字符串文字->常量字符*:指向指针的数组 职能2:

textBuffer->a:标识转换 EAtomId_测试->EAtomId:标识转换 字符串文字->省略号:省略号转换 依次比较这些转换,您可以:

功能1与功能2相同 功能2优于功能1 功能1优于功能2
因此,函数1和函数2对于所有转换都不是那么好,因此调用是不明确的。

这两个点都不适用。ADL在这里并不真正适用,因为它只添加到查找集,但这两个函数对普通查找都是可见的。函数模板和非模板函数的消歧仅适用于两种函数类型相同的情况。13.3.3/1.@Richard Corden:我本来打算超负荷解决的。这些并不是作为要点,而是为了完整性。我的命令不正确-我应该先把我最后说的话放在前面,然后再添加关于ADL的要点。这两个要点都不适用。ADL在这里并不真正适用,因为它只添加到查找集,但这两个函数对普通查找都是可见的。函数模板和非模板函数的消歧仅适用于两种函数类型相同的情况。13.3.3/1.@Richard Corden:我本来打算超负荷解决的。这些并不是作为要点,而是为了完整性。我的命令不正确-我应该把我最后说的放在第一位,然后添加关于ADL的要点。谢谢你的详细回复。如果我没弄错的话,在param 2中,可能的提升和积分转换和身份转换一样强大?我原以为编译器会选择identity而不是需要转换才能工作的情况。除了重新排序
你能建议一个解决这个问题的方法吗?我要做的是为静态大小的字符串缓冲区提供自动长度安全性。同时,我们有两种方法来指定格式字符串-通过文字和通过atom从字典中查找以进行本地化。感谢您的详细回复。如果我没弄错的话,在param 2中,可能的提升和积分转换和身份转换一样强大?我原以为编译器会选择identity而不是需要转换才能工作的情况。除了重新排序外,你能建议一种解决这个问题的方法吗?我要做的是为静态大小的字符串缓冲区提供自动长度安全性。同时,我们有两种方法来指定格式字符串——通过文字和通过atom从字典中查找以进行本地化。
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");
}