2012-01-04 2 views
1

Вот очень простой пример специализации функций в C++. Я думаю, что это должно сработать, но компилятор Visual Studio дает мне сообщение о двусмысленности.С ++ Функция специализации не разрешена?

template <class T> T min(T a, T b) { 
    if(a < b) return a; 
    else return b; 
} 

string min(string str1, string str2) { 
    if(str1.length() < str2.length()) return str1; 
    return str2; 
} 


void main(int argc, char* argv[]) 
{ 
    int n=12, p=15; 
    string str1= "monsieur", str2= "bonjour" ; 

    cout << min(n,p) << endl;   
    cout << min(str1, str2) << endl; 
} 

На самом деле он говорит, что «мин (п, р) Неоднозначный и не знаю, какие функции для вызова. Вероятно, это тривиальная задача, но я не понял, проблема. Я попытался следующие заголовки тоже:

template<> string min(string str1, string str2) 

и:

template<> string min<string>(string str1, string str2) 

Может кто-то помочь мне

+1

Сообщите нам точные сообщения об ошибках и строки, на которые они ссылаются (в противном случае мы можем только догадываться, так как ваш примерный код, вероятно, не совсем минимальный). –

+3

Использование min как имя, вероятно, вызовет проблемы, попробуйте сначала что-то вроде «бла», которое не будет сталкиваться со стандартными идентификаторами. – Gary

ответ

2

Неверный шаблон, который не требует преобразования, всегда лучше соответствует. То есть, если бы это были единственные определения min(), проблем не было бы (например, переименования функции min на что-то другое устранило бы двусмысленность). Неопределенность между template <typename T> T const& std::min(T const&, T const&) и вы templatized версии. Другой исправление удалить с помощью декларации и явного указания имен из пространства имен std, то есть следующий код компилируется нормально:

#include <iostream> 
#include <string> 

template <class T> T min(T a, T b) { 
    return a < b? a: b; 
} 

std::string min(std::string str1, std::string str2) { 
    return str1.length() < str2.length()? str1: str2; 
}  

int main() 
{ 
    int n=12, p=15; 
    std::string str1= "monsieur", str2= "bonjour" ; 

    std::cout << min(n,p) << "\n";   
    std::cout << min(str1, str2) << "\n"; 
} 

Пожалуйста, обратите внимание, что версия вашего min()std::string является не специализации, но перегрузка! При вызове функции, как вы это делали, это не имеет значения, и она выберет версию, как ожидалось. Однако, при вызове функции в то время как явное указания аргумента шаблона не будет:

min(str1, str2);    // calls string overload 
min<std::string>(str1, str2); // calls the function template (*) 

(*) На самом деле, min<std::string>(str1, str2), опять же, неоднозначно с версией из имен std из-за аргумент зависимого взгляд вверх; если бы он был назван по-разному, он бы назвал версию шаблона.

Если вы хотите действительно специализировать функцию, можно было бы написать что-то вроде этого:

template <> std::string min<std::string>(std::string, std::string) { ... } 

Тем не менее, вот несколько случайных заметок о программе, не связанные с неоднозначностью и специализации:

  • В C++ main()всегда должно быть объявлено о возврате int. Разрешено опускать оператор return в main(), но некоторые компиляторы не получают этого права. Для портативного кода лучше всего использовать возврат int и просто вернуть 0 (или EXIT_SUCCESSdeclared in <stdlib.h>).
  • Вы почти наверняка хотите передать эти аргументы по ссылке const: копирование строк не так дорого, особенно для небольших std::string (поскольку современные реализации std::string, похоже, используют небольшую оптимизацию строк), но она также не является бесплатной.Если объекты достаточно велики, это может быть проблемой производительности.
  • Я предполагаю, что это всего лишь тест для игры с перегрузкой/специализацией. В противном случае, std::string версия min() не рекомендуется, так как ведет себя непредсказуемым образом.
  • ваши тестовые строки плохо выбраны, потому что они не показывают, что фактически используется перегрузка/специализация.
  • сильно злоупотребляет и делает что-то другое, чем большинство людей думает, что это делает: в дополнение к вставке символа новой строки ('\ n') он также сбрасывает std :: ostream. Это последняя неожиданная неожиданность, и я обнаружил, что она создает серьезные проблемы с производительностью довольно часто. Если вы действительно не собираетесь очищать поток, просто напишите \ n.
+0

Очень впечатлен вашим ответом! Спасибо, я многому научился! – Zonata

2

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

Изменение имени функции сделало ваш пример правильно составленным для меня.

+0

Можете поверить, что это была проблема. Спасибо и жалею, что беспокоили людей за такой тривиальный вопрос. – Zonata

+0

Не беспокойтесь. В идеале, более одного человека узнают что-то из этого вопроса! –