LINUX.ORG.RU

Знатокам Ц\Ц+++


0

0

Принимаю в функцию с переменным числом параметров эти самые параметры. По первому из них прописанному с типом как положено определяю например, что следующий параметр должен быть double. А гадкий юзер (вернее коллега програмист) передает его как int. Можно ли как-то отследить эту ситуацию и что-то сделать. Пристальное рассматривание printf(char* format, ... ) подсказало только то, что с этим все довольно плохо (;


>Знатокам Ц\Ц+++

Для начала выучить как называется язык, ага.

Можно ли как-то отследить эту ситуацию и что-то сделать.


Договорись с коллегой и объясни ему, что он должен тебе передавать, это самый простой вариант.

Zhbert ★★★★★
()

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

Zenom ★★★
()
Ответ на: комментарий от Zhbert

>> Знатокам Ц\Ц+++

Для начала выучить как называется язык, ага.

Подучи историю ИТ (так у вас этот предмет в школе называется), потом учи дялю )))

shelA
() автор топика
Ответ на: комментарий от Boy_from_Jungle

> Если я тебя понял, то ты не осилил приведение типов?!

Осилил годов как десять назад ) Впрочем приведи примерчик как ты в этих случаях разруливаешь ситуацию. Кто знает, может подскажешь чего путного. Как говорил поручик Ржевский «Век живи, век учись» перекладывая серебряный портсигар из кармана брюк в пиджак )

shelA
() автор топика

>Принимаю в функцию с переменным числом параметров...

Не нужно. Используй перегруженные функции, или передавай массив, вектор, etc.

annulen ★★★★★
()
Ответ на: комментарий от Zenom

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

Да понятно. Мой пост скорее плач, ну не ужели нельзя было в с99 или хотя бы в с0++х ввести специальный вызов который бы сохранял количество и sizeof параметров! ;(

shelA
() автор топика
Ответ на: комментарий от annulen

>> Принимаю в функцию с переменным числом параметров...

Не нужно. Используй перегруженные функции, или передавай массив, вектор, etc.

Хорошая мысль), но идея с переменным числом параметров у меня как раз и возникла после того как я обломался при переносе GCC кода в MSVC. Этот их MSVC нифига не смог скомпилить темплейтованную оверлоад функцию.

shelA
() автор топика
Ответ на: комментарий от shelA

или код не вполне правильный (скорее всего, GCC закрывает глаза на многие виды небрежностей), или MSVC говно

annulen ★★★★★
()
Ответ на: комментарий от annulen

> или код не вполне правильный (скорее всего, GCC закрывает глаза на многие виды небрежностей), или MSVC говно

Похоже MSVC нераспарсил таки (по стандарту вроде такое должно было распарсится). Это был код их с++ врапера evlib, если интересно могу пример сюда вытатащить, но наверно уже завтра )

shelA
() автор топика
Ответ на: комментарий от annulen

+1, интеловский компилятор очень строг. В самый раз для начинающих программистов.

hibou ★★★★★
()
Ответ на: комментарий от Zenom

> Нельзя

можно, причем даже без c++0x,

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

www_linux_org_ru ★★★★★
()

ну и с с++0х можно обойтись без выкрутас с %

Variadic templates may also apply to functions, thus not only providing a type-safe add-on to variadic functions (such as printf) - but also allowing a printf-like function to process non-trivial objects.

template<typename... Params> void printf(const std::string &strFormat, Params... parameters);

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Booster

Задача не понятна. Чего там не распарсил MSVC? Решаем костылями?

Не распарсил он следуещее:
Весь код можно посмотреть здесь: http://cvs.schmorp.de/libev/ev++.h?view=markup

// Это методы класса

    // method callback
    template<class K, void (K::*method)(watcher &w, int)>
    void set (K *object) throw ()
    {
      set_ (object, method_thunk<K, method>);
    }

    // no-argument callback
    template<class K, void (K::*method)()>
    void set (K *object) throw ()
    {
      set_ (object, method_noargs_thunk<K, method>);
    }

// Вызываю как-то так:
class timed_work

{

	ev::timer _timer;


	void on_timer( ev::timer& timer_watcher, int revents)

	{

		cout << "KU-KU!" << endl;

	}



public:

	timed_work(void)

	{

		_timer.set<timed_work, &timed_work::on_timer> (this);

		_timer.start( 0.0, 1.0 );

	}

};

Так вот MSVC9 дает на это странную ошибку типа не может привести типы к вызову второго метода (того что без аргументов). При эттом странно игнорируя наличие первого который полностью подходит под описание. Незнаю может быть в ЬЫМС есть какие-то фишки которые помогут понять пациенту какой именно метод нужен?

Буду брагодарен за подсказку. Хотя так как мне нужен только первый метод, второй я тупо заифундефил для MSVC - помогло ))).

shelA
() автор топика
Ответ на: комментарий от www_linux_org_ru

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

Ну что вы как дети? Однин не знает что такое Ц++, другому обратный слеш не нравиться )))

cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; // Posix-Printf style

Это ты меня в заблуждение вводишь?)

shelA
() автор топика
Ответ на: комментарий от www_linux_org_ru

>> ну и с с++0х можно обойтись без выкрутас с %

Да насчет с++0х я был не прав ) Кстати можно было бы и ссылочку на вики дать, а то приведенный тобой кусочек слабо отражает все глубину вопроса )

shelA
() автор топика

В gcc есть специальный трюк для проверки параметров printf-подобных функций, что-то типа

[code]int your_func(char *fmt, ...) __like_printf[/code]

Поищи как на самом деле в инклудах.

anonymous
()

shelA, если функция принимает format string в стиле printf - можно пользоваться http://docs.freebsd.org/info/gcc/gcc.info.Function_Attributes.html

`format (ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)'
The `format' attribute specifies that a function takes `printf' or
`scanf' style arguments which should be type-checked against a
format string.

иначе, наверное, никак..

waker ★★★★★
()

В gcc есть специальный трюк для проверки параметров printf-подобных функций, что-то типа

int your_func(char *fmt, ...) __like_printf

Поищи как на самом деле в инклудах.

anonymous
()
Ответ на: комментарий от shelA

> Это ты меня в заблуждение вводишь?

нет, это я на первый раз простил тебе обратный слеш

в следующий раз применишь там обратный слеш и тебя введут в заблуждение — я промолчу

Ну что вы как дети?

достали уже дети, пишущие http:\\example.com\path\to\some\file.htm

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Это ты меня в заблуждение вводишь?

нет, это я на первый раз простил тебе обратный слеш

Спасибо, что простил, о Великий!) Кстати подскажи мне тупоголовому один момент

// Есть функция челен класса
template<class Watcher, class Class, void (Class::*method)(Watcher&, int)>
Watcher* addCallBack(Class *object)
{
	Watcher* watcher = new Watcher();
	watcher->set< Class, method > (object);
	watcher->data = object;
	return watcher;
}

// Которая нормально так себе вызывается из MSVC таким образом
ev::timer * pTimer2 = srv.addCallBack<ev::timer, Test, &Test::on_timer2>(&test);
// GCCу же становится совсем плохо ;)
// Я собственно догадываюсь даже по какой причине ;) ev::timer объявлен как
struct ev::timer : base<ev_timer, ev::timer> { 
...
}
// а set это метод базового класса.

О Великий! Дай совет и я навсегда забуду про обратный слешь; что можно сделать что бы подружить её с GCCом без втыкания в шаблон четвертого параметра.

anonymous
()
Ответ на: комментарий от shelA

Шаблоны головного мозга? Может проще написать по-человечески:

#include <iostream>

using namespace std;

struct watcher {};

// Это методы класса
struct timer
{
// method callback
	template<class K >
	void set (const K *object, void (K::*method) (watcher &w, int)) const throw ()
	{
//		set_ (object, method_thunk<K, method>);
	}

// no-argument callback
	template<class K >
	void set (const K *object, void (K::*method) ()) const throw ()
	{
//		set_ (object, method_noargs_thunk<K, method>);
	}

	void start(double , double ) {}
};

// Вызываю как-то так:
class timed_work
{

	timer _timer;


	void on_timer ( watcher & timer_watcher, int revents)
	{
		cout << "KU-KU!" << endl;
	}

	void on_timer2()
	{
	}

public:

	timed_work (void)
	{

		_timer.set<timed_work> (this, &timed_work::on_timer);
		_timer.set<timed_work> (this, &timed_work::on_timer2);
		_timer.start ( 0.0, 1.0 );
	}

};

int main()
{
	timed_work w;
}
Reset ★★★★★
()
Ответ на: комментарий от anonymous

> о Великий!) Кстати подскажи мне тупоголовому

я это не имел в виду

без втыкания в шаблон четвертого параметра

цель благородная, давай пости (или закинь куда) кусок, который можно было бы скормить g++ и где была бы эта ошибка

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Reset

> Шаблоны головного мозга? Может проще написать по-человечески:

Равновеликий! Хотелось просто обобщенно связывать колбэки с ватчерами и регистрировать их в классе контейнере как-то так:

ev::timer * pTimer2 = srv.addCallBack<ev::timer, Test, &Test::on_timer2>(&test);

ev::sig * pSigInt = srv.addCallBack<ev::sig, Test, &Test::on_SIGINT>(&test);

А не писать под каждый тип ватчера (их где еще 4-5 видов) свою функцию.

anonymous
()
Ответ на: комментарий от www_linux_org_ru

>> без втыкания в шаблон четвертого параметра

цель благородная, давай пости (или закинь куда) кусок, который можно было бы скормить g++ и где была бы эта ошибка

Завтра закину если у меня шаблон головного мозга не случится ;) В принципе «хотелось странного» просто для того, что бы постройнее код выглядел (см. письмо выше).

anonymous
()
Ответ на: комментарий от shelA

> Да понятно. Мой пост скорее плач, ну не ужели нельзя было в с99 или хотя бы в с0++х ввести специальный вызов который бы сохранял количество и sizeof параметров! ;(

ВАМ НУЖЕН НЕ «Си»

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.