Страница 1 из 2
С vs С++
Добавлено: 21 мар 2007, 13:53
i_van
Всегда думал, что С++ как минимум advanced C. Но жизнь иногда ставит в тупик. При попытке миграции с С на С++ возникла проблема, описанная ниже. Пару решений я нашел, но они кривоваты.
Специалисты по С++ подтягиваемся:
Проблема связана с сигнатурой функции greeting. Код приведенный ниже работает в С, но не в С++. Как его элегантно заставить работать в С++?
#include <stdio.h>
void use_int(int *);
void use_float(float *);
void greeting(void (*)(void *), void *);
int main(void) {
int i_age = 22;
float f_age = 22.0;
void *p;
p = &i_age;
greeting(use_int, p); //first call
p = &f_age;
greeting(use_float, p); //second call
//getchar();
return 0;
}
void greeting(void (*fp)(void *), void *q) {
fp(q);
}
void use_int(int *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(float *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
Re: С vs С++
Добавлено: 21 мар 2007, 13:58
ajkj3em
void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
Добавлено: 21 мар 2007, 14:03
Azazello
Deleted: ajkj3em was first

...
Re: С vs С++
Добавлено: 21 мар 2007, 14:16
sz
ajkj3em писал(а):void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
На плюсах нынче кошернее писать:
a = * reinterpret_cast<int*>( r );
Re: С vs С++
Добавлено: 21 мар 2007, 14:41
i_van
ajkj3em писал(а):void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
Я так и выкрутился. Однако при этом use_int() теряет строгое типизирование и может быть вызвана не с первоначально требуемым аргументом int* . В этом-то я и вижу кривизну, которой хотелось бы избежать.
Добавлено: 21 мар 2007, 14:42
sz
Так оно и до этого было нестрого типизированно.
Так что, ничего не потерялось.
Re: С vs С++
Добавлено: 21 мар 2007, 14:44
ajkj3em
i_van писал(а):Я так и выкрутился. Однако при этом use_int() теряет строгое типизирование и может быть вызвана не с первоначально требуемым аргументом int* . В этом-то я и вижу кривизну, которой хотелось бы избежать.
строгое типизирование теряетcя при первом downcast'е в void.
в оригинальном коде ничего не мешает вызвать greeting(use_int, &f_age),
так шта кривизна там присутcтвует и без С++
Добавлено: 21 мар 2007, 15:16
aissp
something like this
template <typename T> void func( void (*fp)(T*), T* q) {
fp(q);
}
calling:
void use_int(int* );
int q;
func(use_int, &q); //u don't need use template keyword here
sorry, havent time to check
good luck
Добавлено: 21 мар 2007, 16:28
Azazello
Ну, если templates использовать, то пожалуй так можно:
Код: Выделить всё
#include <iostream>
#include <typeinfo>
using namespace std;
template < typename TType > struct TypeTraits
{
};
struct TypeTraits< int >
{
static inline void SetPrecision( void )
{
cout << dec;
}
};
struct TypeTraits< float >
{
static inline void SetPrecision( void )
{
cout << fixed;
}
};
struct TypeTraits< double >
{
static inline void SetPrecision( void )
{
cout << scientific;
}
};
template < typename TType > void Greetings( TType fAge )
{
TypeTraits< TType > :: SetPrecision();
cout << "In "<< typeid( TType ).name() << "-type representation, your are " << fAge << " years old." << endl;
}
int main( void )
{
int lAgeI = 22;
float lAgeF = 22;
double lAgeD = 22;
Greetings( lAgeI );
Greetings( lAgeF );
Greetings( lAgeD );
cin.get();
return( 0 );
}
Program output писал(а):
In int-type representation, you are 22 years old.
In float-type representation, you are 22.000000 years old.
In double-type representation, you are 2.200000e+01 years old.
Добавлено: 21 мар 2007, 16:33
ajkj3em
Azazello писал(а):Ну, если templates использовать, то пожалуй так можно:
http://www.ariel.com.au/jokes/The_Evolu ... ammer.html
:-)
Добавлено: 21 мар 2007, 16:45
aissp
ну если мы все хором извращаемся то вынужден поправить код
Код: Выделить всё
template < typename TType, typename MyTraits = TypeTriats<TType> > void Greetings( TType fAge )
{
MyTraits :: SetPrecision();
cout << "In "<< MyTraits::name() << "-type representation, your are " << fAge << " years old." << endl;
}
name() соотвественно тоже должна обрабатываться в классе свойств. Смысл так делать много и никакого одновременно
Добавлено: 21 мар 2007, 17:03
Azazello
I like the Master Programmer version

...
name() соотвественно тоже должна обрабатываться в классе свойств.
С MyTraits согласен - это более "правильный" стиль (торопился, у меня проф. сидел на шее

). А вот по поводу того, класть ли name() в TypeTraits - не уверен. Аргумент такой - в Traits кладутся только разные вещи, а то что можно объединить, надо объединять, иначе код разбухает бесцельно. assip, я правильно понимаю, что Ваш комментарий стилистический и заключается в том, что TypeInfo по своей сути вещь различная для типов и, соответственно, это должно быть отражено в Traits? Или я что-то принципиальное здесь упустил?
Добавлено: 21 мар 2007, 17:40
aissp
лучше на ты а то у меня шок культурный сразу
Вобшем да ты прав, только уточню - трайтс класс уточнений, на етапе проихводства трайтса ты абсолютно точно знаешь тип вызова (для етого класс и служит не так ли?) поетому вызов typeId отпадает сам собой. Мне кажется не очень хороший стиль, когда по сути есть два различных места хранения инфо о типе. ДА и не верю я в корректную работу тайпАйдИ

(ето основная причина)
Добавлено: 21 мар 2007, 20:52
Azazello
aissp писал(а):Мне кажется не очень хороший стиль, когда по сути есть два различных места хранения инфо о типе. ДА и не верю я в корректную работу тайпАйдИ

(ето основная причина)
Согласен - некрасиво дублировать. Просто, RTTI всё равно нужно для dynamic_cast и virtual destructor clean-up, а, значит, TypeInfo уже есть. aissp, то есть, Вы dynamic_cast совсем не пользуете (просто интересно, как люди пишут

) или там какие-то конкретные проблемы с typeid (он же, по моему, просто возвращает ссылку на const type_info)?
Да, простите за "Вы" - привычка

...
Добавлено: 21 мар 2007, 21:27
aissp
да за вы надо отучаться. А то представляешь типа Дорогой иван данилыч косячек то не отсасывайте и не мусольте, передавайте по кругу поджалста...
там с темплатами по коду нигде никакой виртальности нету

точнее она есть но на етапе компиляции тока. А с динамиком - мне кажется единственное место где он применяется ето когда условия изменились настолько что надо передизайнить а на ето нету времени, либо код совсем чужой и никакими адаптерами не спасешься - действия должны происходить внутри кода.
ну например у тя есть список коров и свиней для скотобойни (их с ферм списывают на мфсозаготовки по старости) и все замечательно они у тебя живут под классом жЫвотное. Вдруг оказывается что что у свиней с украины бывает по три ноги и их надо обрабатывать особо. Хозяин библиотеки добавляет функцию bool is3LegExist() которую не вставляет в оьщий интерфейс. и тебе уже передизайнить нету времени - вот тут тебе приходится использовать динамик каст. Если такие запросы на количество заслуженных украниских свинок редки, ты забиваешь на все и делаешь нисъодящее приведение. Мне кажется так. Красивый пример никак в голову не лезет. сорри
с typeid ни разу в жизни не применял на практике. Надо бы поглядеть когда применяется, но сдается мне что цели отладки и такая же ситуации как применеие динамик каста, только еше более екзотичные.
Все сказанное мое сугубое имху