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

发布于 2024-09-27 07:45:12 字数 665 浏览 6 评论 0原文

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

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 ta, const tb) 的函数,它会编译。

I wrote a template function to compare two variables:

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;

}

I get the following error

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

Please explain.
Also if I write cout << compare("hi", "wo"); it compiles properly.
Or if I remove the & and declare the function like int compare(const t a, const t b) it compiles.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

拥醉 2024-10-04 07:45:12

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.

A string literal of N characters is an array of N constant characters with a terminating '\0' afterwards. So type of "hi" is char const[3] and the one of "world" is char const[6].

So if you pass it to the template, t is deduced to two different types. Note that when in a reference parameter, template argument deduction does not transform arrays to pointers.

Also, please check up in comparing pointers to each other. The way you do that won't ever compare the strings lexically, but just the addresses of them, yielding an unspecified value. You can fix the argument deduction bit by having two separate template parameters

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 gives a good error message

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.
痴梦一场 2024-10-04 07:45:12

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

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

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

In C++, as in C, string literals are nul-terminated character arrays. "hi" becomes the character array ['h', 'i', 0]. C++ treats the size of the array as part of its type for templates; the string "hi" is an array of length 3, and the string "world" is an array of length 6, so the compiler can't find a single type t that matches both arrays.

When you try to compile compare("hi", "wo") the compiler finds that type t is const char [3], since both strings -- arrays -- have the same length.

When you drop the &, the arrays decode into const pointers, so the compiler finds that type t is const char *. Note that in this case, you're comparing the pointers to the strings, not their contents.

×眷恋的温暖 2024-10-04 07:45:12

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

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

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

Johannes Schaub - litb showed your problem.

And with that problem, one of the best solution for this case is using Nontype Template Parameters.

template <signed N, signed M>
int compare(const char (&p1) [N], const char (&p2) [M] ){
    return strcmp(p1, p2);
}
×眷恋的温暖 2024-10-04 07:45:12

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

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

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

如果您只编写 (a>b),数组 a 和 b 将衰减为指针,因此您实际上只是比较字符串文字的第一个字符的地址。

The type of the string literal "hi" is const char [3].
The type of the string literal "world" is const char [6].
So they're different types.

Your compare template uses the same type for both parameters, so this won't fly.

Change your compare template to use different types for the two parameters.
Also you will have to provide an overload to compare string literals correctly.

If you just write (a>b), the arrays a and b will decay into pointers, so you'd be really only comparing the addresses of the first characters of the string literals.

╭⌒浅淡时光〆 2024-10-04 07:45:12

模板函数转换为真实函数,编译器将模板类替换为真实类。在您的代码中,您的函数原型表明

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]并且没有歧义。

如果将该函数实现为 intcompare(const ta, const tb),编译器会找到 t 的替代方案:char *。数组将被转换为 const char * ,因此不会有歧义。

Template functions are converted into real function with template classes replaced with real classes by the compiler. In your code, your function prototype indicates that,

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

both a and b must be of same type.

When you call compare("hi", "world");, for compiler there are two different types for a and b because "hi" is of type const char [3] and "world" is of type const char [6]. The compiler cannot implement a good version of compare().

But when you call compare("hi", "wo");, suddenly both becomes of same type: const char [3] and there is no ambiguity.

If you implement the function as int compare(const t a, const t b) the compiler finds an alternative for t: char *. The arrays will be converted into const char * and thus there is no ambiguity.

浴红衣 2024-10-04 07:45:12

如果您需要让比较运算符在 C 样式字符串(char 的 null 终止数组)的模板中工作,则必须有一个专门的模板以及您的模板。通用模板。 棘手的是 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<的类,此模板化函数将会失败。 code>operator== 已定义。 这会造成严重破坏。这看起来非常像使用 C++ 模板将事物强制转换为 C 语言方法。

更好的方法

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

重载运算符

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

使用 std::string

在 C 风格字符串上使用比较运算符的问题可以通过将其替换为 std::string 来解决。 std::string 的一个很好的功能是它已经定义了比较运算符。因此,您可以使用 < 来比较两个 std::string 对象。

总结

不要创建使用 C 风格比较(例如返回 -1、0 或 +1)的模板函数,而是为您的类定义比较运算符并将以 null 结尾的字符数组转换为 std::string< 的实例/代码>。

If you need to have the comparison operators work in a template for C-style strings (null terminated arrays of char), you will have to have a specialized template along with your generic template. The thorn is that C-style strings cannot be compared using the operators.

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

Note: This templated function will fail for all classes that do not have operator< or operator== defined. Which will cause havoc down the road. This looks very much like a using C++ templates to force things into the C language methodology.

A Better Approach

I see two C++ specific features that could make your life easier: Overloading operators and using std::string. Using these features will eliminate your need for the templated functions.

Overloading Operators

One reason for having a templated compare function is because the class doesn't have comparison operators devined (otherwise you would use the operators). So, define the overloaded operators < and ==. The other operators >, >=, <= and != can be defined in terms of the latter two. See boost operators header.

Using std::string

The problem of using comparison operators on C-style strings can be removed by replacing them with std::string. A nice feature of std::string is that it has the comparison operators already defined. Thus you can use < to compare two std::string objects.

Summary

Rather than creating a template function that uses C-style comparing (e.g. return -1, 0, or +1), define comparison operators for your classes and convert null terminated arrays of characters into instances of std::string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文