比较c ++模板中的字符串文字

时间:2010-10-12 18:43:16

标签: c++ string templates compare literals

我写了一个模板函数来比较两个变量:

template <class t>

int compare(const t &a, const t &b) {

if(a>b) return 1;

if (a<b) return -1;

return 0;

}

int main(int argc, const char *argv[])
{

    cout << compare("hi","world");

    return 0;

}

我收到以下错误

../src/templates.cpp: In function ‘int main(int, const char**)’:
../src/templates.cpp:11: error: no matching function for call to ‘compare(const char [3], const char [6])

请解释一下。 此外,如果我写cout << compare("hi", "wo");,它会正确编译。 或者,如果我删除&并声明像int compare(const t a, const t b)这样的函数,则会编译。

6 个答案:

答案 0 :(得分:2)

N个字符的字符串文字是N个常量字符的数组,之后有一个终止'\ 0'。因此,"hi"的类型为char const[3],而"world"的类型为char const[6]

因此,如果将其传递给模板,t将推断为两种不同的类型。请注意,在引用参数中,模板参数推导不会将数组转换为指针。

另外,请检查比较指针。你这样做的方式不会在词法上比较字符串,而只是它们的地址,产生一个未指定的值。您可以通过使用两个单独的模板参数

来修复参数推导位
template <class t, class u>
int compare(const t &a, const u &b) {
  if(a>b) return 1;
  if (a<b) return -1;

  return 0;
}

Clang提供了一个很好的错误消息

main1.cpp:17:5: error: no matching function for call to 'compare'
    compare("hi","world");
    ^~~~~~~
main1.cpp:4:5: note: candidate template ignored: 
  deduced conflicting types for parameter 't' ('char [3]' vs. 'char const[6]')
int compare(const t &a, const t &b) {
    ^
1 error generated.

答案 1 :(得分:1)

在C ++中,与C一样,字符串文字是以空字符结尾的字符数组。 "hi"成为字符数组['h', 'i', 0]。 C ++将数组的大小视为模板类型的一部分;字符串"hi"是一个长度为3的数组,字符串"world"是一个长度为6的数组,因此编译器找不到与两个数组匹配的单个类型t。 / p>

当您尝试编译compare("hi", "wo")时,编译器发现类型tconst char [3],因为两个字符串 - 数组 - 具有相同的长度。

当您删除&时,数组会解码为const指针,因此编译器会发现类型tconst char *。请注意,在这种情况下,您将指针与字符串进行比较,而不是将其内容进行比较。

答案 2 :(得分:0)

字符串文字“hi”的类型是const char [3]。 字符串文字“world”的类型是const char [6]。 所以他们的类型不同。

您的比较模板对两个参数使用相同的类型,因此不会飞。

更改比较模板,为两个参数使用不同的类型。 此外,您必须提供重载以正确比较字符串文字。

如果你只是写(a>b),数组a和b将衰减为指针,所以你真的只是比较字符串文字的第一个字符的地址。

答案 3 :(得分:0)

模板函数转换到实际函数中,编译器将模板类替换为实际类。在您的代码中,您的函数原型指示

int compare(const t &a, const t &b)

ab必须属于同一类型。

当您致电compare("hi", "world");时,对于编译器,ab有两种不同的类型,因为“hi”的类型为const char [3]而“world”属于类型const char [6]。编译器无法实现compare()的良好版本。

但是当你致电compare("hi", "wo");时,突然两者都变成了同一类型:const char [3]并且没有歧义。

如果将函数实现为int compare(const t a, const t b),编译器会找到t:char *的替代方法。数组将转换为const char *,因此没有歧义。

答案 4 :(得分:0)

如果你需要让比较运算符在C样式字符串的模板中工作(char的空终止数组),你必须有一个专门的模板和你的通用模板。 刺是无法使用运算符比较C风格的字符串。

template <class t>
int compare(const char * a, const char * b)
{
  return strcmp(a, b);
}

template <class t>
int compare(const t& a, const t& b)
{
  return (a == b) ? 0 : ((a < b) ? -1 : 1);
}

注意:对于没有定义operator<operator==的所有类,此模板化函数将失败。这会导致破坏。这看起来非常像使用C ++模板来强制使用C语言方法。

更好的方法

我看到两个特定于C ++的功能可以让您的生活更轻松:重载运算符并使用std::string。使用这些功能将消除您对模板化功能的需求。

重载运算符

使用模板化 compare 函数的一个原因是因为类没有设置比较运算符(否则您将使用运算符)。因此,请定义重载的运算符<==。其他运算符>, >=, <=!=可以根据后两者来定义。请参阅boost运营商标题。

使用std::string

可以通过用std::string替换它们来消除在C风格字符串上使用比较运算符的问题。 std::string的一个很好的特性是它已经定义了比较运算符。因此,您可以使用<来比较两个std::string个对象。

摘要

不是创建使用C样式比较的模板函数(例如返回-1,0或+1),而是为类定义比较运算符,并将空终止的字符数组转换为std::string的实例。

答案 5 :(得分:0)

Johannes Schaub - litb显示了你的问题。

对于这个问题,本案例的最佳解决方案之一是使用非类型模板参数

template <signed N, signed M>
int compare(const char (&p1) [N], const char (&p2) [M] ){
    return strcmp(p1, p2);
}
相关问题