是否有可能合法地重载字符串文字和const char *?

时间:2013-05-23 07:44:14

标签: c++ templates c++11 overloading

C ++ 11中是否有可能重载const char*和字符串文字(const char[])? 我们的想法是避免在已知此长度时调用strlen来查找字符串长度。

这个片段在G ++ 4.8和Clang ++ 3.2上打破了:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

template<typename T, int N>
void length(const T(&data)[N]) {
  printf("%u[]\n", N - 1);
}

template<typename T>
void length(const T* data) {
  printf("*%u\n", (unsigned)strlen(data));
}

int main() {
  length("hello");
  const char* p = "hello";
  length(p);
  return 0;
}

错误(Clang):

test2.cpp:16:3: error: call to 'length' is ambiguous
  length("hello");
  ^~~~~~
test2.cpp:6:6: note: candidate function [with T = char, N = 6]
void length(const T(&data)[N]) {
     ^
test2.cpp:11:6: note: candidate function [with T = char]
void length(const T* data) {
     ^
1 error generated.

黑客攻击,这似乎有效:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

template<typename T, int N>
void length(const T(&data)[N]) {
  printf("%u[]\n", N - 1);
}

template<typename T>
void length(T&& data) {
  printf("*%u\n", (unsigned)strlen(data));
}

const char *foo() {
   return "bar";
}

int main() {
  length("hello");
  const char* p = "hello";
  length(p);
  length(foo());
  return 0;
}

这是有效的C ++ 11吗?删除数组特化时,字符串文字似乎在T&&上重载。是什么原因导致解决这个问题,而不是第一个代码片段中的那个?

1 个答案:

答案 0 :(得分:4)

在第一种情况下,在重载分辨率期间,你有一个完美的匹配,不需要转换数组到指针的转换(在“左值变换”类别中,以及左值到左值和函数到指针转换)。仅通过左值变换进行的差异不足以使重载决策成为赢家。

在第二种情况下,在重载解析期间,两个函数具有完全相同的参数类型。然后,作为最后手段的部分排序发现第二个模板将接受您传递给它的所有参数,而第一个模板只接受数组。因此,第二种情况下的第一个模板更加专业化并被采用。


至于你的另一个问题 - 不,不能专门为字符串文字重载。你总是会随身携带相同大小的数组。