boost_typeof
От: jyuyjiyuijyu  
Дата: 03.03.11 03:59
Оценка:
Всем привет.
уже неделю мучает один вопрос есть макрос
(тем 20 до этой есть мой вопрос об этом же но более развернуто)
#define zoo(e,...) \
blabla<typeof(e)>(__VA_ARGS__)
в него передается список парметров
и имя перегруженной функции
как подходящий тип функции вывести ?
например имеем
strstr(char*,const char*);
strstr(const char*,const char*);
вот вызывем макрос так к примеру
char *pp = 0;
const char *cc = 0;
zoo(strstr, pp, cc);
нужно в макросе получить тип char*(char*,const char*);
невозможно подставить boost_typeof ругается
на то что незнает тип какой именно из пергруженных
функций нужен а указать ему какие
аргументы прилагаются никак не выходит
ну чтоб он вывел точный тип исходя из аргументов
как такое сделать ?
Re: boost_typeof
От: _nn_ www.nemerleweb.com
Дата: 03.03.11 09:48
Оценка: 1 (1)
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>ну чтоб он вывел точный тип исходя из аргументов

J>как такое сделать ?


Все решаемо

В общих чертах идея проста.
Нам нужна функция, которая может принять указатель на функцию и возвратить указатель на функцию, но где нам достаточно будет указать типы аргументов, а возвращаемый тип выведется сам:
template<typename T1, typename T2, typename R>
R (*check (R (*f)(T1, T2))) (T1, T2)
{
    return f;
}


Пояснение:
Имя функции будет check.
Имя параметра функции будет f.
Тип у f: R (*)(T1, T2)
Возвращаемый тип у check: R (*)(T1, T2)
Такой изврат необходим, чтобы компилятор мог вывести тип R автоматически.

Теперь положим мы имеем функции:
void ff(int, char){}
void ff(long, long){}
int ff(int, void*){return 0;}


Следующие вызовы скомпилируются без проблем:
check<int, char>(ff);
check<long long>ff);
check<int, void*>(ff);


Ну а теперь дело за малым, приделать макрос и BOOST_TYPEOF:

int i = 0;
char c = 0;

typedef BOOST_TYPEOF( (check<BOOST_TYPEOF(i), BOOST_TYPEOF(c)>(ff)) ) p_ff_int_char;

Примечание: Дополнительные скобки нужны из-за запятой.
Если не нужен указатель, можно убрать с помощью boost::remove_pointer.

  Полный код
#include <iostream>

void ff(int, char){std::cout<<"ff(int,char)\n";}
void ff(long, long){std::cout<<"ff(long,long)\n";}
int ff(int, void*){std::cout<<"ff(int,void*)\n";return 0;}

template<typename T1, typename T2, typename R>
R (*check (R (*f)(T1, T2))) (T1, T2)
{
    return f;
}

int main()
{    
    int i = 0;
    char c = 0;
    long l = 0;
    void* pv = 0;

    typedef BOOST_TYPEOF( (check<BOOST_TYPEOF(i), BOOST_TYPEOF(c)>(ff)) ) p_ff_int_char;
    p_ff_int_char pff1 = ff;
    pff1(0, 0);

    typedef BOOST_TYPEOF( (check<BOOST_TYPEOF(l), BOOST_TYPEOF(l)>(ff)) ) p_ff_long_long;
    p_ff_long_long pff2 = ff;
    pff2(0, 0);

    typedef BOOST_TYPEOF( (check<BOOST_TYPEOF(i), BOOST_TYPEOF(pv)>(ff)) ) p_ff_int_pvoid;
    p_ff_int_pvoid pff3 = ff;
    pff3(0, 0);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: boost_typeof
От: diver_ru  
Дата: 03.03.11 10:42
Оценка: +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет.

J>уже неделю мучает один вопрос есть макрос
J>(тем 20 до этой есть мой вопрос об этом же но более развернуто)
J>...
J>вот вызывем макрос так к примеру
J>...
J>невозможно подставить boost_typeof ругается
J>на то что незнает тип какой именно из пергруженных
J>функций нужен а указать ему какие
J>аргументы прилагаются никак не выходит
J>ну чтоб он вывел точный тип исходя из аргументов
J>как такое сделать ?

блин, твое разбиение строк и пунктуация взрывает мне мозг
Re[2]: boost_typeof
От: jyuyjiyuijyu  
Дата: 03.03.11 11:14
Оценка:
Здравствуйте, _nn_, Вы писали:
...
template<typename T1, typename T2, typename R>
R (*check (R (__cdecl*f)(T1, T2))) (T1, T2)
{
return f;
}
template<typename T1, typename T2, typename R>
R (__stdcall*check (R (__stdcall*f)(T1, T2))) (T1, T2)
{
return f;
}
спасибо за внимание проверил я Ваш код
обнаружил вот какую проблему
допустим имеем такую функу
void fi(char*,char*){}
вот...
допустим вызов такой
#define zoo(e,...) \
blabla<remove_pointer<typeof(check<UNPACK_TYPE(__VA_ARGS__)>(e))>::type>(__VA_ARGS__)
...
zoo(fi,0,"");
...
ну или любой другой тип ожидаемого указателя вместо которого передается 0
подставляем список типов из __VA_ARGS__ в check
получается
check<int,const char*>(fi)
в итоге check раскрывается в
template<int, const char*, void>
void (*check (void (*f)(int, const char*))) (int, const char*)
{
return f;
}
и происходит конфликт ожидаемого void(*)(int,const char*)
с по факту переданным void(*)(char*,char*)
придется вместо 0 для нулевых указателей
всегда передавать реальную переменную указатель
или на месте делать кастинг zoo(fi, (char*)0, "")
а так да проблема решается и с calling convention и с
overloaded function но это недопустимо
придется весь существющий код править где передается 0 вместо нулевого указателя
да и новый писать так не удобно (не стандартно)
Re[3]: boost_typeof
От: jyuyjiyuijyu  
Дата: 03.03.11 12:48
Оценка:
вот просто когда юзаем функции
strstr(char*,const char*);
strstr(const char*,const char*);
...
char *pp = 0;
const char *cc = 0;
strstr(pp,cc);
strstr(cc,cc);
компилятор быстро находит нужную
перегруженную версию и знает полный тип ret_t calling_t(arg1_t, и т.д.)
у нас есть аргументы и имя функции
надо просто указать компилятору найти все перегрузки
сопоставить и вернуть тип если что то подошло
но как это правильно спросить у компилятора
великая тайна по видимому
Re[4]: boost_typeof
От: _nn_ www.nemerleweb.com
Дата: 03.03.11 13:21
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>вот просто когда юзаем функции

J>strstr(char*,const char*);
J>strstr(const char*,const char*);
J>...
J>char *pp = 0;
J>const char *cc = 0;
J>strstr(pp,cc);
J>strstr(cc,cc);
J>компилятор быстро находит нужную
J>перегруженную версию и знает полный тип ret_t calling_t(arg1_t, и т.д.)
Он находит , так как вы передаете ему правильные типы.
А попробуйте передать неправильные то сразу будет проблема:
strstr(0, 0);

ambiguous call to overloaded function


J>у нас есть аргументы и имя функции

J>надо просто указать компилятору найти все перегрузки
J>сопоставить и вернуть тип если что то подошло
J>но как это правильно спросить у компилятора
J>великая тайна по видимому
Тут сложнее чем вы пишете.
Вы хотите найти все функции где есть возможность конвертации типов, а не точное сопоставление типов.

Т.е. имея
void f(char* , char*)
вы хотите получить эту функцию имея два аргумента 0,0.
Эти два аргумента имеют типы int, int.
Но в случае нуля они могут стать и char*.

Теперь, BOOST_TYPEOF(0) нам даст int и никогда не даст ничего другого.
А нам нужно в компайл тайм проверить что это 0, а потом удостовериться ,что функцию принимает указатель и сказать что типы совместимы.

При этом все равно будут неоднозначности.
Вот в случае strstr, вызов BOOST_TYPEOF(strstr(0,0)) что должен дать ? 1-ю или 2-ю версию ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: boost_typeof
От: Danchik Украина  
Дата: 04.03.11 10:19
Оценка: :)))
Здравствуйте, diver_ru, Вы писали:

[Skip]

_>блин, твое разбиение строк и пунктуация взрывает мне мозг


Ник тоже так не слабо вышибает, видать будет еще один Александреску
Re[5]: boost_typeof
От: jyuyjiyuijyu  
Дата: 03.05.11 00:56
Оценка:
Здравствуйте, _nn_, Вы писали:

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


J>>вот просто когда юзаем функции

J>>strstr(char*,const char*);
J>>strstr(const char*,const char*);
J>>...
J>>char *pp = 0;
J>>const char *cc = 0;
J>>strstr(pp,cc);
J>>strstr(cc,cc);
J>>компилятор быстро находит нужную
J>>перегруженную версию и знает полный тип ret_t calling_t(arg1_t, и т.д.)
__>Он находит , так как вы передаете ему правильные типы.
__>А попробуйте передать неправильные то сразу будет проблема:
__>
strstr(0, 0);

__>

__> ambiguous call to overloaded function


J>>у нас есть аргументы и имя функции

J>>надо просто указать компилятору найти все перегрузки
J>>сопоставить и вернуть тип если что то подошло
J>>но как это правильно спросить у компилятора
J>>великая тайна по видимому
__>Тут сложнее чем вы пишете.
__>Вы хотите найти все функции где есть возможность конвертации типов, а не точное сопоставление типов.
нет я хочу узнать тип после того как компилятор определит есть ли подходящая функция
и если нет неоднозначности тоесть так как он всегда делает
__>Т.е. имея
__>void f(char* , char*)
__>вы хотите получить эту функцию имея два аргумента 0,0.
__>Эти два аргумента имеют типы int, int.
__>Но в случае нуля они могут стать и char*.
вот если переданы нули и если можно вызвать f то он должен дать ее тип
так как бы поступил он если бы вызвал то пусть вернет тип или ошибку

__>Теперь, BOOST_TYPEOF(0) нам даст int и никогда не даст ничего другого.

__>А нам нужно в компайл тайм проверить что это 0, а потом удостовериться ,что функцию принимает указатель и сказать что типы совместимы.

__>При этом все равно будут неоднозначности.

__>Вот в случае strstr, вызов BOOST_TYPEOF(strstr(0,0)) что должен дать ? 1-ю или 2-ю версию ?
это и в обычной жизни ошибка я говорю про законные варианты например
0 для strstr может быть только вторым и если передают
char *p = 0;
const char *pp = 0;
macro(strstr,p,0);
или
macro(strstr,pp,0);
я хочу узнать какой тип выберет компилятор

задача звучит предельно просто узнать точный тип перегруженной функции
имея на руках ее имя и аргументы к ней
и ничего немогу придумать как только не пытался
Re: Offtop
От: rg45 СССР  
Дата: 03.05.11 04:41
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет.

J>уже неделю мучает один вопрос есть макрос
J>(тем 20 до этой есть мой вопрос об этом же но более развернуто)
J>#define zoo(e,...) \
J>blabla<typeof(e)>(__VA_ARGS__)
J>в него передается список парметров
J>и имя перегруженной функции
J>как подходящий тип функции вывести ?
J>например имеем
J>strstr(char*,const char*);
J>strstr(const char*,const char*);
J>вот вызывем макрос так к примеру
J>char *pp = 0;
J>const char *cc = 0;
J>zoo(strstr, pp, cc);
J>нужно в макросе получить тип char*(char*,const char*);

Концепция несколько странная: получается, для того, чтобы вывести тип формальных параметров, необходимо сконструировать объекты всех фактических. А если функция принимает какой-то "тяжелый" тип? Пусть даже по ссылке — все равно его придется создать — и только лишь для того, чтобы просто вывести тип?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Offtop
От: jyuyjiyuijyu  
Дата: 07.05.11 17:45
Оценка:
Здравствуйте, rg45, Вы писали:

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


J>>Всем привет.

J>>уже неделю мучает один вопрос есть макрос
J>>(тем 20 до этой есть мой вопрос об этом же но более развернуто)
J>>#define zoo(e,...) \
J>>blabla<typeof(e)>(__VA_ARGS__)
J>>в него передается список парметров
J>>и имя перегруженной функции
J>>как подходящий тип функции вывести ?
J>>например имеем
J>>strstr(char*,const char*);
J>>strstr(const char*,const char*);
J>>вот вызывем макрос так к примеру
J>>char *pp = 0;
J>>const char *cc = 0;
J>>zoo(strstr, pp, cc);
J>>нужно в макросе получить тип char*(char*,const char*);

R>Концепция несколько странная: получается, для того, чтобы вывести тип формальных параметров, необходимо сконструировать объекты всех фактических. А если функция принимает какой-то "тяжелый" тип? Пусть даже по ссылке — все равно его придется создать — и только лишь для того, чтобы просто вывести тип?

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