Шаблонные функции, непонятно...
От: Vamp Россия  
Дата: 17.07.03 10:36
Оценка:
Читал Страуструпа, много думал, но не все понял.
Явная специализация нужна для задания поведения шаблонной функции специфичного для переданных параметров, так? Причем функция выводится по параметрам.
Допустим, я хочу написать шаблонную функцию сравнения и реализовать две специализации. Одну принимающие сами объекты, а другую — указатели на объекты.
То есть, идея такая:


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




Разумеется, ничего не выходит — оба раза вызывается первая функция. Как-то можно вызвать требуемую? Или я вообще ничего не понял вовсе?
Спасибо.
Да здравствует мыло душистое и веревка пушистая.
Re: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 10:43
Оценка:
Здравствуйте, Vamp, Вы писали:

Может так?
template < class T > 
bool cmp <T*>( const T* a, const T* b ) 
{
    cout << "Pointer template function called" << endl;
        return (*a<*b);
}
Re[2]: Шаблонные функции, непонятно...
От: Vamp Россия  
Дата: 17.07.03 10:46
Оценка:
Не-а. Все равно вызывает первую функцию. Даже если писать

cmp<int *>(&g, &i);
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Шаблонные функции, непонятно...
От: Аноним  
Дата: 17.07.03 10:58
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Не-а. Все равно вызывает первую функцию. Даже если писать


#include <iostream>

using namespace std;

template<class T>
bool cmp(T a, T b)
{
  cout << "General template function called" << endl;
  return  (a<b);
}

template<>
bool cmp<int*>(int* a, int* b)
{
  cout << "Pointer template function called" << endl;
  return (*a<*b);
}

void main()
{
int j=5, i=7;
cmp(i, j);
cmp(&i, &j);
}
Re[4]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>template<>

А>bool cmp<int*>(int* a, int* b)
А>{
А> cout << "Pointer template function called" << endl;
А> return (*a<*b);
А>}

И так для каждого типа?

ЗЫ: Как же это все-таки сделать?
Re[5]: Шаблонные функции, непонятно...
От: e-Xecutor Россия  
Дата: 17.07.03 11:21
Оценка:
Здравствуйте, UGN, Вы писали:

UGN>Здравствуйте, Аноним, Вы писали:


А>>template<>

А>>bool cmp<int*>(int* a, int* b)
А>>{
А>> cout << "Pointer template function called" << endl;
А>> return (*a<*b);
А>>}

UGN>И так для каждого типа?


UGN>ЗЫ: Как же это все-таки сделать?


Так что хочется то?
Вообще для pointers, или для конкретного типа?
Если вообще для Pointers, то достаточно из оригинального примера убрать const
Re[6]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:26
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

EX>Так что хочется то?

EX>Вообще для pointers, или для конкретного типа?
Что хочется Vamp, я не знаю. А мне теперь хочется для указателей вообще.
Я тут тоже читаю 13 главу. Только опытов еще не ставил.

EX>Если вообще для Pointers, то достаточно из оригинального примера убрать const

Пробовал?
VC7 жалуется на неоднозначность.
Re[7]: Шаблонные функции, непонятно...
От: Holms США  
Дата: 17.07.03 11:32
Оценка:
Здравствуйте, UGN, Вы писали:

UGN>VC7 жалуется на неоднозначность.


vot takoi primer MinGW kompilit bez problem, i raboatet tak kak tebe nado


    int j=5, g=7;
    cmp(g, j);
    cmp((const int*)&g, (const int*)&j);

vedii vtoraia funcktia prinimaet const ukazateli
... << RSDN@Home 1.1 beta 1 >>
The life is relative and reversible.
Re[7]: Шаблонные функции, непонятно...
От: e-Xecutor Россия  
Дата: 17.07.03 11:34
Оценка:
Здравствуйте, 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 указателей и просто указателей сгенерятся две разные функции
Re: Шаблонные функции, непонятно...
От: Bell Россия  
Дата: 17.07.03 11:36
Оценка:
Здравствуйте, Vamp, Вы писали:

а компилятор-то, судя по всему, MSVC6
Любите книгу — источник знаний (с) М.Горький
Re[8]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:39
Оценка:
Здравствуйте, Holms, Вы писали:

H>vedii vtoraia funcktia prinimaet const ukazateli


я const давно уже убрал...
не работает.

Кто-нить на VC7 может проверить?
Re[8]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:41
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

EX>Но! Для const указателей и просто указателей сгенерятся две разные функции


Да это понятно. Я у себя const сразу убрал...

Твой вариант у меня не работает... (VC7)

То ли лыжи не едут...

Кстати, мне бы хотелось видеть первый шаблон в форме

template<class T> bool cmp( T a,  T b)

а не как у тебя 

template<class T> bool cmp(const T& a, const T& b)
Re[2]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:45
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Vamp, Вы писали:


B>а компилятор-то, судя по всему, MSVC6

B>

MSVC6, MSVC7, за другими идти далеко...

Bell, напиши, плз, кошерный вариант partial specialization

А то вот это не работает
template<class T> bool cmp( T a, T b)
template<class T> bool cmp < T* > ( T* a, T* b)


Так же принимаются объяснения кто тут не того...
Re[9]: Шаблонные функции, непонятно...
От: e-Xecutor Россия  
Дата: 17.07.03 11:47
Оценка:
Здравствуйте, 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 может получится нехорошо...
Re[9]: Шаблонные функции, непонятно...
От: Vamp Россия  
Дата: 17.07.03 11:50
Оценка:
Конст — не конст дела не меняет. Специализировать для каждого типа (инт, флоат, ...) — совершенно не хочется. Идея именно такая, как ее понял UGN. Написать две реализации, одна из которых будет работать с самим объектом, а вторая с указателем на него.
Да здравствует мыло душистое и веревка пушистая.
Re[10]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 11:55
Оценка:
Здравствуйте, e-Xecutor, Вы писали:


EX>Попробовал: vc7 от VS.NET 2003 13.10.3077


Это, наверное, уже VC 7.1?

EX>Только в твоём случае если T!= pod type может получится нехорошо...


Да это фиг с ним. Мне для академического интересу.

Там БС рассказывает как это классно все получается.
Был Generic, а потом сделали еще один только для указателей...
Re[3]: Шаблонные функции, непонятно...
От: PM  
Дата: 17.07.03 11:59
Оценка:
B>> а компилятор-то, судя по всему, MSVC6
B>>
U>
U> MSVC6, MSVC7, за другими идти далеко...
U> А то вот это не работает
U>
 U> template<class T> bool cmp( T a, T b)
 U> template<class T> bool cmp < T* > ( T* a, T* b)
 U>

U>
U> Так же принимаются объяснения кто тут не того...
Это частичная специализация, которую версии Visual C++ меньше 7.1 не поддерживают в принципе
Posted via RSDN NNTP Server 1.6 RC1
Re[10]: Шаблонные функции, непонятно...
От: MaximE Великобритания  
Дата: 17.07.03 12:01
Оценка:
Здравствуйте, 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)); // накормим шаблон ссылками
}
Re[11]: Шаблонные функции, непонятно...
От: Vamp Россия  
Дата: 17.07.03 12:03
Оценка:
Что-то я уже вообще ничего не понимаю.

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 в данном случае не запрещает просто изменять значение переменной через указатель, одновременно разрешая передавать адреса константных объектов?
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Шаблонные функции, непонятно...
От: Павел Кузнецов  
Дата: 17.07.03 13:57
Оценка: 14 (1)
Здравствуйте, PM, Вы писали:

U>>
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> поддерживают в принципе

Частичную специализацию шаблонов функций, в принципе, не поддерживают никакие компиляторы.
По крайней мере, стандарт ее точно не разрешает.
Posted via RSDN NNTP Server 1.6 RC1
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 14:02
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Частичную специализацию шаблонов функций, в принципе, не поддерживают никакие компиляторы.

ПК>По крайней мере, стандарт ее точно не разрешает.

Точно. У БС пример с классами... Куда смотрели мои глаза?

А почему решили не делать такое с функциями?
Re[5]: Шаблонные функции, непонятно...
От: PM  
Дата: 17.07.03 14:04
Оценка:
U>>>
 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>> поддерживают в принципе
ПК> Частичную специализацию шаблонов функций, в принципе, не
ПК> поддерживают никакие компиляторы. По крайней мере, стандарт ее точно не
ПК> разрешает.
Просмотрел, что это не методы класса.
Пора отдыхать
Posted via RSDN NNTP Server 1.6 RC1
Re[3]: Шаблонные функции, непонятно...
От: Bell Россия  
Дата: 17.07.03 14:13
Оценка:
Здравствуйте, UGN, Вы писали:

тут дело не в частичной специализации, а в overload resolution для шаблонных функций. А у VC6 с этим вроде не все в порядке.
Любите книгу — источник знаний (с) М.Горький
Re[6]: Шаблонные функции, непонятно...
От: Павел Кузнецов  
Дата: 17.07.03 14:30
Оценка: 14 (1)
Здравствуйте, 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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 14:34
Оценка:
Здравствуйте, Bell, Вы писали:

B>тут дело не в частичной специализации, а в overload resolution для шаблонных функций. А у VC6 с этим вроде не все в порядке.


Т.е. на этапе перебора всех подходящих шаблонных функций и
определения более специализированных компилятор считает обе формы идентичными...
Отсюда и неопределенность.

А если сделать перегрузку обычной функцией с подходящими параметрами,
то на следующем этапе компилятор выкинет шаблоны и все будет ок. Так?

Теперь по поводу указателей на константу.

Если определить int n, то &n имеет тип int*.
А для выведенных аргументов применять всяческие приведения нельзя,
поэтому второй шаблон с константными квалификаторами игнорировался
и оба раза использовался общий шаблон. Правильно?
Re[5]: Шаблонные функции, непонятно...
От: Bell Россия  
Дата: 17.07.03 14:44
Оценка: 14 (1)
Здравствуйте, UGN, Вы писали:


UGN>Т.е. на этапе перебора всех подходящих шаблонных функций и

UGN>определения более специализированных компилятор считает обе формы идентичными...
UGN>Отсюда и неопределенность.

Да.

UGN>А если сделать перегрузку обычной функцией с подходящими параметрами,

UGN>то на следующем этапе компилятор выкинет шаблоны и все будет ок. Так?

Да. Обычная функция имеет преимущество перед шаблонной.

UGN>Теперь по поводу указателей на константу.


UGN>Если определить int n, то &n имеет тип int*.

UGN>А для выведенных аргументов применять всяческие приведения нельзя,
UGN>поэтому второй шаблон с константными квалификаторами игнорировался
UGN>и оба раза использовался общий шаблон. Правильно?

Не совсем понял о чем речь — "второй шаблон" — это где?
Любите книгу — источник знаний (с) М.Горький
Re[7]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 14:49
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Потому что посчитали, что раз есть перегрузка шаблонов функций, то частичная специализация

ПК>для них не нужна.

Понятно...

А вот еще вопросик по 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 C

template< class T >
int compare( const String<T>& str1, const String<T>& str2 ); // compare using Cmp<T>


Собственно вопрос: А почему во втором случае будет использоваться Cmp<T>, откуда он там возьмется?
Я что-то упустил?
Re[6]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 14:50
Оценка:
Здравствуйте, Bell, Вы писали:

UGN>>Если определить int n, то &n имеет тип int*.

UGN>>А для выведенных аргументов применять всяческие приведения нельзя,
UGN>>поэтому второй шаблон с константными квалификаторами игнорировался
UGN>>и оба раза использовался общий шаблон. Правильно?

B>Не совсем понял о чем речь — "второй шаблон" — это где?


здесь
Автор: Vamp
Дата: 17.07.03


template<class T> bool cmp(T a, T b) 
template<class T> bool cmp(const T* a, const T* b)
Re[8]: Шаблонные функции, непонятно...
От: Павел Кузнецов  
Дата: 17.07.03 16:36
Оценка: 21 (1)
Здравствуйте, UGN, Вы писали:

U>
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
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: Шаблонные функции, непонятно...
От: UGN  
Дата: 17.07.03 16:42
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

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, а что со вторым я ниппоньял...
Спасибо.
Re[7]: Шаблонные функции, непонятно...
От: Bell Россия  
Дата: 18.07.03 06:19
Оценка:
Здравствуйте, UGN, Вы писали:

UGN>Здравствуйте, Bell, Вы писали:


UGN>>>Если определить int n, то &n имеет тип int*.

UGN>>>А для выведенных аргументов применять всяческие приведения нельзя,
UGN>>>поэтому второй шаблон с константными квалификаторами игнорировался
UGN>>>и оба раза использовался общий шаблон. Правильно?

B>>Не совсем понял о чем речь — "второй шаблон" — это где?


UGN>здесь
Автор: Vamp
Дата: 17.07.03

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 рассматриваются специализации обоих шаблонов, полученные во время дедуцирования аргументов. Они (специадизации) имеют такие сигнатуры:
bool <int*> cmp(int*, int*)//1
bool <int> cmp(const int*, const int*)//2

очевидно, что специализация 1 выигрывает.
Если написать две обычные (в смысле не шаблонные) функции с такими же сигнатурами, то:

bool cmp(int* p1, int*p2)//1
{
//...
}

bool cmp(const int* p1, const int*p2)//2
{
//...
}

//...
int n;
cmp(&n, &n);


будет вызвана функция 1. Тут даже VC6 все делает так, как надо
Любите книгу — источник знаний (с) М.Горький
Re[8]: Шаблонные функции, непонятно...
От: UGN  
Дата: 18.07.03 06:32
Оценка:
Здравствуйте, Bell, Вы писали:

B>Ага, теперь ясно.

B>Тут ты не прав: при overload resolution рассматриваются специализации обоих шаблонов, полученные во время дедуцирования аргументов. Они (специадизации) имеют такие сигнатуры:
B>
B>bool <int*> cmp(int*, int*)//1
B>bool <int> cmp(const int*, const int*)//2
B>

B>очевидно, что специализация 1 выигрывает.

Дык и я о том же, наверное...

Почему выигрывает первая специализация?
Потому что const int* и просто int* — разные типы... Так?
Компилятор мог бы использовать второй шаблон,
сконвертировав типы аргументов, но это ему запрещено.
Поэтому он выводит нужную реализацию из общего шаблона. Так?
Re[9]: Шаблонные функции, непонятно...
От: Bell Россия  
Дата: 18.07.03 07:04
Оценка: 14 (1)
Здравствуйте, UGN, Вы писали:


UGN>Почему выигрывает первая специализация?

UGN>Потому что const int* и просто int* — разные типы... Так?
Да.
UGN>Компилятор мог бы использовать второй шаблон,
UGN>сконвертировав типы аргументов,
конечно, если бы не было более подходящего варианта.
UGN>но это ему запрещено.
Вовсе нет. убери из кода первый шаблон, и компилятор спокойно организует вызов ыторого.
UGN>Поэтому он выводит нужную реализацию из общего шаблона. Так?
Компилятор использует специализацию первого шаблона из-за того того, что полученные типы параметров ближе к реальному типу передаваемых аргументов.
Любите книгу — источник знаний (с) М.Горький
Re: Шаблонные функции, непонятно...
От: ilnar Россия  
Дата: 21.07.03 09:51
Оценка:
Здравствуйте, Vamp, Вы писали:


так и должно быть. первое соответствие выбирается. попробуй тип шаблонного параметра укажи

V>
V>template<class T> bool cmp(T a, T b) {
V>    cout << "General template function called" << endl;
V>        return  (a<b);

V>}

V>template<class T> bool cmp(const T* a, const T* b) {
V>    cout << "Pointer template function called" << endl;
V>        return (*a<*b);
V>}

V>int j=5, i=7;
V>cmp<int>(g, j);
V>cmp<int>(&g, &j);
V>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.