Ошибка создания шаблона - PullRequest
5 голосов
/ 27 июня 2009

У меня есть функция шаблона «сравнить», определенная ниже.

#include<iostream>
using namespace std;

template<typename T>
void compare(const T&a, const T& b)
{
    cout<<"Inside compare"<<endl;
}

main()
{
compare("aa","bb");
compare("aa","bbbb");
}

Когда я создаю экземпляр сравнения со строковыми литералами одинаковой длины, компилятор не жалуется. Когда я делаю это с литералами разной длины, он говорит: «ошибка: нет подходящей функции для вызова для сравнения (const char [3], const char [5])»

Я запутался, так как функция сравнения должна создаваться с помощью символьного указателя, а не массив символов. Разве строковые литералы не должны всегда указывать на указатель?

Ответы [ 3 ]

6 голосов
/ 27 июня 2009

Ваш пример компилируется, если вы измените объявление на:

void compare(const T* a, const T* b)

Причина в том, что типы массивов символов разных размеров на самом деле разные типы. Если бы вы использовали sizeof(T) в функции шаблона, компилятор не знал бы, как устранить неоднозначность. В приведенном выше объявлении вы вызываете функцию шаблона с типами указателя на T, которые компилятор с радостью разрешит как const char* при передаче строки символов.

4 голосов
/ 27 июня 2009

Как указано в ответе и комментариях Грега, проблема заключается в двух разных типах массивов (поскольку это и есть строковые литералы). Возможно, вы захотите оставить функцию как есть для универсальных типов, но перегружайте ее для указателей и массивов символов, это в основном полезно, когда вы хотите обрабатывать их немного по-другому.

void compare(char const* a, char const* b) {
    // do something, possibly use strlen()
}

template<int N1, int N2>
void compare(char const (&a)[N1], char const (&b)[N2]) {
    // ...
}

Если вы хотите указать, что сравнение должно явно указывать символьные указатели, то массивы автоматически преобразуются:

compare<char const*>("aa", "bbbb");

С другой стороны, может быть, можно написать сравнение для работы с двумя разными типами? Это может быть полезно и для других типов, например, возможно, он вызывает f(a), если a.size() < b.size(), и f(b) в противном случае (с перегруженной f). (T1 и T2 могут быть одного и того же типа ниже, и это заменит вашу функцию вместо того, чтобы перегружать ее как две выше.)

template<typename T1, typename T2>
void compare(T1 const& a, T2 const& b) {
    // ...
}
3 голосов
/ 27 июня 2009

Компилятор предпочтет интерпретировать строковые литералы как символьные буферы, если это возможно. Если нет, он может интерпретировать их как const char *. Однако компилятор не собирается возвращаться назад, чтобы попытаться найти лучшую интерпретацию T. Это не так сложно. Как только он решает, что T является const char [3], он движется дальше. Оценить второй аргумент не удается.

Если вы позвоните с

compare(static_cast<const char *>("aa"),static_cast<const char *>("bbbb"));

Ты в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...