U> template< class T, class C >
U> int compare( const String<T>& str1, const String<T>& str2 ); // compare using C
U> template< class T >
U> int compare( const String<T>& str1, const String<T>& str2 ); // compare using Cmp<T>
U>
U> А почему во втором случае будет использоваться Cmp<T>, откуда он там возьмется?
Ее будет использовать реализация второго варианта. Например, так:
template< class T >
int compare( const String<T>& str1, const String<T>& str2 ) // compare using Cmp<T>
{
return compare<Cmp<T>, T>(str1, str2);
}
Posted via RSDN NNTP Server 1.6 RC1
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, UGN, Вы писали:
ПК>> Частичную специализацию шаблонов функций <...> стандарт <...> точно не разрешает.
U> А почему решили не делать такое с функциями?
Потому что посчитали, что раз есть перегрузка шаблонов функций, то частичная специализация
для них не нужна.
Это, в некотором роде, спорное утверждение. См., например: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1295.htm.
Вкратце там сказано, что в namespace std нельзя добавлять перегруженные функции/шаблоны функций,
поэтому некоторые стандартные компоненты "подменить" нельзя. Следствием этого является, в частности,
то, что перегрузить std::swap для своих шаблонов нельзя.
С другой стороны, стандарт не вполне точен в отношении того, как именно разработчики стандартной
библиотеки должны вызывать стандартные функции: используя полностью квалифицированные имена, или
нет (дефекты #225 и #229 стандартной библиотеки), поэтому, вполне возможно, что поиска, зависящего
от аргументов, окажется достаточным для этих целей.
Posted via RSDN NNTP Server 1.6 RC1
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
UGN>Т.е. на этапе перебора всех подходящих шаблонных функций и UGN>определения более специализированных компилятор считает обе формы идентичными... UGN>Отсюда и неопределенность.
Да.
UGN>А если сделать перегрузку обычной функцией с подходящими параметрами, UGN>то на следующем этапе компилятор выкинет шаблоны и все будет ок. Так?
Да. Обычная функция имеет преимущество перед шаблонной.
UGN>Теперь по поводу указателей на константу.
UGN>Если определить int n, то &n имеет тип int*. UGN>А для выведенных аргументов применять всяческие приведения нельзя, UGN>поэтому второй шаблон с константными квалификаторами игнорировался UGN>и оба раза использовался общий шаблон. Правильно?
Не совсем понял о чем речь — "второй шаблон" — это где?
UGN>Почему выигрывает первая специализация? UGN>Потому что const int* и просто int* — разные типы... Так?
Да. UGN>Компилятор мог бы использовать второй шаблон, UGN>сконвертировав типы аргументов,
конечно, если бы не было более подходящего варианта. UGN>но это ему запрещено.
Вовсе нет. убери из кода первый шаблон, и компилятор спокойно организует вызов ыторого. UGN>Поэтому он выводит нужную реализацию из общего шаблона. Так?
Компилятор использует специализацию первого шаблона из-за того того, что полученные типы параметров ближе к реальному типу передаваемых аргументов.
Читал Страуструпа, много думал, но не все понял.
Явная специализация нужна для задания поведения шаблонной функции специфичного для переданных параметров, так? Причем функция выводится по параметрам.
Допустим, я хочу написать шаблонную функцию сравнения и реализовать две специализации. Одну принимающие сами объекты, а другую — указатели на объекты.
То есть, идея такая:
template<class T> bool cmp(T a, T b) {
cout << "General template function called" << endl;
return (a<b);
}
template<class T> bool cmp(const T* a, const T* b) {
cout << "Pointer template function called" << endl;
return (*a<*b);
}
int j=5, i=7;
cmp(g, j);
cmp(&g, &j);
Разумеется, ничего не выходит — оба раза вызывается первая функция. Как-то можно вызвать требуемую? Или я вообще ничего не понял вовсе?
Спасибо.
Здравствуйте, UGN, Вы писали:
UGN>Здравствуйте, Аноним, Вы писали:
А>>template<> А>>bool cmp<int*>(int* a, int* b) А>>{ А>> cout << "Pointer template function called" << endl; А>> return (*a<*b); А>>}
UGN>И так для каждого типа?
UGN>ЗЫ: Как же это все-таки сделать?
Так что хочется то?
Вообще для pointers, или для конкретного типа?
Если вообще для Pointers, то достаточно из оригинального примера убрать const
Здравствуйте, e-Xecutor, Вы писали:
EX>Так что хочется то? EX>Вообще для pointers, или для конкретного типа?
Что хочется Vamp, я не знаю. А мне теперь хочется для указателей вообще.
Я тут тоже читаю 13 главу. Только опытов еще не ставил.
EX>Если вообще для Pointers, то достаточно из оригинального примера убрать const
Пробовал?
VC7 жалуется на неоднозначность.
Здравствуйте, UGN, Вы писали:
UGN>Здравствуйте, e-Xecutor, Вы писали:
EX>>Так что хочется то? EX>>Вообще для pointers, или для конкретного типа? UGN>Что хочется Vamp, я не знаю. А мне теперь хочется для указателей вообще. UGN>Я тут тоже читаю 13 главу. Только опытов еще не ставил.
EX>>Если вообще для Pointers, то достаточно из оригинального примера убрать const UGN>Пробовал? UGN>VC7 жалуется на неоднозначность.
#include <iostream>
using namespace std;
template<class T>
bool cmp(const T& a, const T& b)
{
cout << "General template function called" << endl;
return (a<b);
}
template<class T>
bool cmp(T* a, T* b)
{
cout << "Pointer template function called" << endl;
return (*a<*b);
}
void main()
{
int j=5, i=7;
cmp(i, j);
cmp(&i, &j);
const int a=1,b=2;
cmp(a,b);
cmp(&a,&b);
}
нормально компиляется и работает.
Но! Для const указателей и просто указателей сгенерятся две разные функции
Здравствуйте, UGN, Вы писали:
UGN>Здравствуйте, e-Xecutor, Вы писали:
EX>>Но! Для const указателей и просто указателей сгенерятся две разные функции
UGN>Да это понятно. Я у себя const сразу убрал...
UGN>Твой вариант у меня не работает... (VC7)
Попробовал:
vc7 от VS.NET 2003 13.10.3077
icl 7.1 7.1 Build 20030307Z
bcc32 5.6
везде компиляется и работает так как надо.
UGN>То ли лыжи не едут...
UGN>Кстати, мне бы хотелось видеть первый шаблон в форме
UGN>
UGN>template<class T> bool cmp( T a, T b)
UGN>а не как у тебя
UGN>template<class T> bool cmp(const T& a, const T& b)
UGN>
Ну... на здоровье
И так тоже компиляется и работает.
Только в твоём случае если T!= pod type может получится нехорошо...
Конст — не конст дела не меняет. Специализировать для каждого типа (инт, флоат, ...) — совершенно не хочется. Идея именно такая, как ее понял UGN. Написать две реализации, одна из которых будет работать с самим объектом, а вторая с указателем на него.
Здравствуйте, e-Xecutor, Вы писали:
UGN>>Кстати, мне бы хотелось видеть первый шаблон в форме
UGN>>
UGN>>template<class T> bool cmp( T a, T b)
UGN>>а не как у тебя
UGN>>template<class T> bool cmp(const T& a, const T& b)
UGN>>
EX>Ну... на здоровье EX>И так тоже компиляется и работает.
EX>Только в твоём случае если T!= pod type может получится нехорошо...
Как раз для этого был придуман boost::reference_wrapper<>.
#include <boost/ref.hpp>
template<class T> bool cmp( T a, T b);
struct some {};
void f()
{
some a, b;
cmp(boost::ref(a), boost::ref(b)); // накормим шаблон ссылками
}
template<class T>
bool cmp(const T& a, const T& b)
{
cout << "General template function called" << endl;
return (a<b);
}
template<class T>
bool cmp(T* a, T* b )
{
cout << "Pointer template function called" << endl;
return (*a<*b);
}
int g=5, i=7;
cmp(g, i);
cmp(&g, &i);
Работает именно так, как хотелось. А если вставить в сиганатуру второй функции const, не работает. Разве const в данном случае не запрещает просто изменять значение переменной через указатель, одновременно разрешая передавать адреса константных объектов?
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Частичную специализацию шаблонов функций, в принципе, не поддерживают никакие компиляторы. ПК>По крайней мере, стандарт ее точно не разрешает.
Точно. У БС пример с классами... Куда смотрели мои глаза?
U>>> template<class T> bool cmp( T a, T b)
U>>> template<class T> bool cmp < T* > ( T* a, T* b)
U>>>
P>> Это частичная специализация, которую версии Visual C++ меньше 7.1 не P>> поддерживают в принципе ПК> Частичную специализацию шаблонов функций, в принципе, не ПК> поддерживают никакие компиляторы. По крайней мере, стандарт ее точно не ПК> разрешает.
Просмотрел, что это не методы класса.
Пора отдыхать
Здравствуйте, Bell, Вы писали:
B>тут дело не в частичной специализации, а в overload resolution для шаблонных функций. А у VC6 с этим вроде не все в порядке.
Т.е. на этапе перебора всех подходящих шаблонных функций и
определения более специализированных компилятор считает обе формы идентичными...
Отсюда и неопределенность.
А если сделать перегрузку обычной функцией с подходящими параметрами,
то на следующем этапе компилятор выкинет шаблоны и все будет ок. Так?
Теперь по поводу указателей на константу.
Если определить int n, то &n имеет тип int*.
А для выведенных аргументов применять всяческие приведения нельзя,
поэтому второй шаблон с константными квалификаторами игнорировался
и оба раза использовался общий шаблон. Правильно?
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Потому что посчитали, что раз есть перегрузка шаблонов функций, то частичная специализация ПК>для них не нужна.
Понятно...
А вот еще вопросик по 13 главе. С++ Programming Language SE (3)
В самом начале п.13.4.1 Default Template Parameters приводится пример
Explicitly specifying the comparison criteria for each call is tedious. Fortunately, it is easy to pick
a default so that only uncommon comparison criteria have to be explicitly specified. This can be
implemented through overloading:
template< class T, class C >
int compare( const String<T>& str1, const String<T>& str2 ); // compare using Ctemplate< class T >
int compare( const String<T>& str1, const String<T>& str2 ); // compare using Cmp<T>
Собственно вопрос: А почему во втором случае будет использоваться Cmp<T>, откуда он там возьмется?
Я что-то упустил?
Здравствуйте, Bell, Вы писали:
UGN>>Если определить int n, то &n имеет тип int*. UGN>>А для выведенных аргументов применять всяческие приведения нельзя, UGN>>поэтому второй шаблон с константными квалификаторами игнорировался UGN>>и оба раза использовался общий шаблон. Правильно?
B>Не совсем понял о чем речь — "второй шаблон" — это где?
Здравствуйте, Павел Кузнецов, Вы писали:
U>> А почему во втором случае будет использоваться Cmp<T>, откуда он там возьмется?
ПК>Ее будет использовать реализация второго варианта. Например, так:
ПК>
ПК>template< class T >
ПК>int compare( const String<T>& str1, const String<T>& str2 ) // compare using Cmp<T>
ПК>{
ПК> return compare<Cmp<T>, T>(str1, str2);
ПК>}
ПК>
А, просто другая реализация... А то я уж подумал, что там какая-то магия...
Для первого варианта реализация есть и там используется C, а что со вторым я ниппоньял...
Спасибо.
Здравствуйте, UGN, Вы писали:
UGN>Здравствуйте, Bell, Вы писали:
UGN>>>Если определить int n, то &n имеет тип int*. UGN>>>А для выведенных аргументов применять всяческие приведения нельзя, UGN>>>поэтому второй шаблон с константными квалификаторами игнорировался UGN>>>и оба раза использовался общий шаблон. Правильно?
B>>Не совсем понял о чем речь — "второй шаблон" — это где?
UGN>здесь
UGN>template<class T> bool cmp(T a, T b)
UGN>template<class T> bool cmp(const T* a, const T* b)
UGN>
Ага, теперь ясно.
Тут ты не прав: при overload resolution рассматриваются специализации обоих шаблонов, полученные во время дедуцирования аргументов. Они (специадизации) имеют такие сигнатуры:
Здравствуйте, Bell, Вы писали:
B>Ага, теперь ясно. B>Тут ты не прав: при overload resolution рассматриваются специализации обоих шаблонов, полученные во время дедуцирования аргументов. Они (специадизации) имеют такие сигнатуры: B>
Почему выигрывает первая специализация?
Потому что const int* и просто int* — разные типы... Так?
Компилятор мог бы использовать второй шаблон,
сконвертировав типы аргументов, но это ему запрещено.
Поэтому он выводит нужную реализацию из общего шаблона. Так?