Вопрос по C++ templates...

Все, что вы хотели знать о программизме, но боялись спросить.
Ответить
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Вопрос по C++ templates...

Сообщение Azazello »

Нижеследующий код компилируется и работает:

Код: Выделить всё

template< typename _TType > class TFoo
 {
  public:
   typedef _TType TType;

  protected:
   TFoo(){}
   TFoo( const TFoo& ){}

   const TFoo& operator =( const TFoo& ){}

  public:
   template< typename TTypeAnother > static TType Bar( TTypeAnother fDummy ); 
 };

template< typename TType > template< typename TTypeAnother > TType TFoo< TType > :: Bar( TTypeAnother fDummy )
 {
  return( TType( fDummy ) );
 }

//----------------------------------------------------------------------------------

int main()
 {
  const double lDbl = -123.123;
  int lInt = TFoo< int > :: Bar( lDbl );

  return( 0 ); 
 }
При изменении на

Код: Выделить всё

template< typename TTypeAnother = int > static TType Bar( TTypeAnother fDummy );
не компилируется - выдаёт "> is expected". Почему? Компилятор Borland.
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Сообщение Azazello »

Вопрос разрешился.
Аватара пользователя
Marmot
Графоман
Сообщения: 39279
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Caulfeild
Контактная информация:

Сообщение Marmot »

Azazello писал(а):Вопрос разрешился.
Ой, не а я не успел какашками пошвырятся, жалость какая :)
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Сообщение Azazello »

Пожалуйста, швыряйтесь ;). Только объясните, почему

Код: Выделить всё

Template functions, and class partial specializations, may not use default expressions in their template parameter lists. Only primary template declarations may do this.
Аватара пользователя
Marmot
Графоман
Сообщения: 39279
Зарегистрирован: 17 фев 2003, 17:58
Откуда: Caulfeild
Контактная информация:

Сообщение Marmot »

Azazello писал(а): Только объясните, почему

Код: Выделить всё

Template functions, and class partial specializations, may not use default expressions in their template parameter lists. Only primary template declarations may do this.
Это не ко мне, я потому на С++ и не пишу что там уже даже страусинный труп и то, похоже не все понимает :)
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

Сообщение aissp »

Ну если без правила - то сам понимаешь эта конкретная твоя запись имеет мало смысла, при выведении функции Bar компилятор будет всегда руководствоваться типом переданного в ету функцию аргумента и никогда твоим параметром по умолчанию.

Если говорить про правило, то помниться мне что я где то читал что возникают сложности при реализации компиляторов. По сему мне кажется, чтобы не затягивать с выходом стандарта часть вещей просто декларативно запретили (предположение) и так язык получился лучше чем Ява какая от которой тока шаг до байсика. (утверждение) 8)
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Сообщение Azazello »

Это я понимаю. Просто, непонятно было, чем принципиально это отличается от

Код: Выделить всё

template< typename _TType = int > class TFoo
 {
  ...
 };

TFoo<> lFoo;_i // TFoo< int >
TFoo< double > lFoo_d; //  TFoo< double >
То есть, если default argument в специализации класса для "удобства", то и

Код: Выделить всё

template< typename _TType = int > void Bar( _TType fDummy = 0 )
 {
  ...
 }

Bar(); // call void Bar( int ) with default argument
Bar( double( 5 ) ); // call void Bar( double )
тоже для "удобства" вроде. Не совсем очевидно, какие заморочки у компилятора могут здесь быть. Просто интересно было бы узнать, может тут что действительно принципиальное.
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

Сообщение aissp »

ответ - не знаю:) могу тока пообещать, что если узнаю то непременно поделюсь :)
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Сообщение Azazello »

aissp писал(а):ответ - не знаю:) могу тока пообещать, что если узнаю то непременно поделюсь :)
Сразу чувствуется - брат-сипласпласщик, в беде не бросит, всегда добрым словом подбодрит. Не то что эти яващики, вечно дерьмом в тебя норовят бросить. ;)...
Аватара пользователя
sz
Маньяк
Сообщения: 1266
Зарегистрирован: 17 фев 2003, 19:34

Сообщение sz »

aissp писал(а):Ну если без правила - то сам понимаешь эта конкретная твоя запись имеет мало смысла, при выведении функции Bar компилятор будет всегда руководствоваться типом переданного в ету функцию аргумента и никогда твоим параметром по умолчанию.

Если говорить про правило, то помниться мне что я где то читал что возникают сложности при реализации компиляторов. По сему мне кажется, чтобы не затягивать с выходом стандарта часть вещей просто декларативно запретили (предположение) и так язык получился лучше чем Ява какая от которой тока шаг до байсика. (утверждение) 8)
На самом деле, причина в глупом изначальном решении Страуса, что темплейтные функции могут разрешаться без явного указания параметра темплейта.

То есть допускается:

template<class T>
T abs( T val ) { return val < 0 ? -val : val;

int i = 10;
int j = abs( i );
float f1 = -1.0f;
float f2 = abs( f1 );

Тогда если сделать параметр дефолтовым: template<class T = int>
То у компилятора неоднозначность - abs(f1) - что мы хотим? Использования дефолтового параметра темплейта, или генерации функции для float?

Если бы Страус в свое время подумал на шаг вперед, то конечно потребовал бы явного указания всегда:

template<class T = int>
T abs( T val ) { return val < 0 ? -val : val;

int i = 10;
int j = abs<int>( i );
float f1 = -1.2f;
float f2 = abs<float>( f1 ); // f2 = 1.2f
float f3 = abs( f1 ); // f3 = 1.0f - используется T=int поэтому идет приведение от float к int и обратно.

Ну а теперь поздно исправлять - слишком много кода работать перестанет.
Аватара пользователя
aissp
Маньяк
Сообщения: 2710
Зарегистрирован: 07 ноя 2005, 09:51

Сообщение aissp »

Хе хе
(1) Ну вообще то не страус виноват - там комитет ето раз,
(2) фром С++ модерастед
This is true in C++03, but will change in C++0x. Default template
parameters are going to be allowed also on function templates.
Вобщем я остался при своем мнение пока :)
Аватара пользователя
sz
Маньяк
Сообщения: 1266
Зарегистрирован: 17 фев 2003, 19:34

Сообщение sz »

aissp писал(а):Хе хе
(1) Ну вообще то не страус виноват - там комитет ето раз,
(2) фром С++ модерастед
This is true in C++03, but will change in C++0x. Default template
parameters are going to be allowed also on function templates.
Вобщем я остался при своем мнение пока :)
Комитет тут не при чем. Когда это сделали, никакого комитета вообще еще не было.
Аватара пользователя
Azazello
Житель
Сообщения: 769
Зарегистрирован: 16 янв 2007, 04:31

Сообщение Azazello »

sz писал(а):...Тогда если сделать параметр дефолтовым: template<class T = int>
То у компилятора неоднозначность - abs(f1) - что мы хотим? Использования дефолтового параметра темплейта, или генерации функции для float?
По-моему, неоднозначности здесь нет (или не должно быть) - если тип аргумента не совпадает с default argument, то мы хотим сгенерировать новую функцию. В неком роде, это тоже самое что и

Код: Выделить всё

double Bar( double fDummy )
 {
  return( fDummy );
 }

int Bar( int fDummy )
 {
  return( fDummy );
 }

//---------------------------------------------------------------
int main()
 {
  int lInt = 5;
  double lDbl = 5;
  char lChr = 5;

  lInt = Bar( lInt ); // call int Bar( int )
  lDbl = Bar( lDbl ); // call double Bar( double )
  lInt = Bar( lDbl ); // call double Bar( double )
  lChr = Bar( lChr ); // call int Bar( int )

  return( 0 );
 }
Здесь нет никакой неоднозначности - тип аргумента определяет вызов. Компилятор смотрит есть ли функция с таким типом аргумента, который мы передаём. Если не, то есть ли функция, к типу аргумента которой можно преобразовать переданный тип - неоднозначности тоже нет (например, char преобразуется в первую очередь к int, но если нет int, то к double).
В случае с template компилятор должен генерировать новую функцию, если нет функции с точно таким типом аргумента как переданный - это не нарушает логики templates. То есть, единственно (или, по крайней мере, очевидный пример) когда default argument в template функции используется, это когда у нас есть default value для аргумента функции и мы опускаем аргумент при вызове функции - та же логика определяет класс, когда мы опускаем тип template. По-моему, так.
Ответить