Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.09.2013, 09:56   #1
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию Variadic macros

Добрый день!
Можно ли реализовать:
Код:
void f(const char *s1,
       const char *s2)
{
    cout<<s1<<"\n"<<s2;
}

#define Mm(...)     f(#__VA_ARGS__)

int main()
{
    Mm(Hello, world !!!);
    return 0;
}
Операция #__VA_ARGS__ формирует - "Hello, world !!!", возможно ли сформировать - "Hello", "world !!!" ?
220Volt вне форума Ответить с цитированием
Старый 14.09.2013, 14:50   #2
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

В общем вопрос решил, сделал такую штуку:
Код:
#include <windows.h>
#include <string>


#define f_lib_PRVAR(...)                            \
{                                                   \
    std::string res;                                \
    Debug_message<bool>::create_mes(res,            \
                                    #__VA_ARGS__,   \
                                    0,              \
                                    __VA_ARGS__);   \
    MessageBoxA(NULL, res.c_str(), "", MB_OK);      \
}

template <typename ...>
    struct Debug_message
    {
        template <typename _Ty, typename ..._Other>
            static void create_mes(std::string &res,
                                   const std::string &description,
                                   size_t desc_pos,
                                   _Ty var,
                                   _Other... other)
            {
                if(description[desc_pos]  == ' ')
                    ++ desc_pos;
                size_t comma_pos = description.find(',', desc_pos);
                res += description.substr(desc_pos, comma_pos - desc_pos);
                res += " = ";
                res += std::to_string(var);
                res += "\n";

                Debug_message<_Other...>::create_mes(res,
                                                     description,
                                                     comma_pos + 1,
                                                     other...);

                return;
            }
    };

template <>
    struct Debug_message<>
    {
        static void create_mes(std::string &,
                               const std::string &,
                               size_t) {}
    };


int main()
{
    int n_count = 234;
    int len = 12;
    double low = 1.43;

    f_lib_PRVAR(n_count, len, low);
    return 0;
}
Надоело каждый раз создавать запутаные отладочные сообщения, решил сделать один раз и по-взрослому ))
Изображения
Тип файла: png Результат.png (11.6 Кб, 10 просмотров)
220Volt вне форума Ответить с цитированием
Старый 14.09.2013, 15:53   #3
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

У препроцессора нет средств для выделения слов в строках )
Как раз хотел спросить "зачем это?"
Но, вцелом прикольно, макрос, я так пнимаю, нужен чтобы имена переменных извлечь.
Мне кажется, возможно это как-то проще сделать (я не проверял, но полагаю).

И должно быть, как-то от std::to_string возможно отказаться (и ни к чему оно тут, не по-взрослому выходит - только для встроенных типов сейчас возможно отладочную информацию получить).
rrrFer вне форума Ответить с цитированием
Старый 14.09.2013, 16:36   #4
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
...макрос, я так пнимаю, нужен чтобы имена переменных извлечь. ...
В точку.
Цитата:
Сообщение от rrrFer Посмотреть сообщение
...не по-взрослому выходит - только для встроенных типов сейчас возможно отладочную информацию получить ...
Есть такой вариант:
Код:
struct Man
{
    const char *name;
};

namespace std
{
    std::string to_string(const Man &man)
    {
        return man.name;
    }
}

int main()
{
    Man man {"Tom"};
    int n_count = 234;
    int len = 12;
    double low = 1.43;

    f_lib_PRVAR(n_count, len, low, man);
    return 0;
}

Последний раз редактировалось 220Volt; 14.09.2013 в 16:39.
220Volt вне форума Ответить с цитированием
Старый 14.09.2013, 17:30   #5
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Окончательный вариант с возможность вывода отладочной информации для пользовательских типов (может кому пригодится):
Код:
#include <windows.h>
#include <string>


#define f_lib_PRVAR(...)                            \
{                                                   \
    std::string res;                                \
    Debug_message<bool>::create_mes(res,            \
                                    #__VA_ARGS__,   \
                                    0,              \
                                    __VA_ARGS__);   \
    MessageBoxA(NULL, res.c_str(), "", MB_OK);      \
}

namespace std
{
    template <typename _Ty>
        std::string to_string(const _Ty &);
}

template <typename ...>
    struct Debug_message
    {
        template <typename _Ty, typename ..._Other>
            static void create_mes(std::string &res,
                                   const std::string &description,
                                   size_t desc_pos,
                                   _Ty var,
                                   _Other... other)
            {
                if(description[desc_pos]  == ' ')
                    ++ desc_pos;
                size_t comma_pos = description.find(',', desc_pos);
                res += description.substr(desc_pos, comma_pos - desc_pos);
                res += " = ";
                res += std::to_string(var);
                res += "\n";

                Debug_message<_Other...>::create_mes(res,
                                                     description,
                                                     comma_pos + 1,
                                                     other...);

                return;
            }
    };

template <>
    struct Debug_message<>
    {
        static void create_mes(std::string &,
                               const std::string &,
                               size_t) {}
    };

struct Man
{ 
    const char *name;
};

namespace std
{
template <>
    std::string to_string<Man>(const Man &man)  // Перегрузка to_string для пользоват. типа
    {
        return man.name;
    }
}


int main()
{
    Man man {"Tom"};
    int n_count = 234;
    int len = 12;
    double low = 1.43;

    f_lib_PRVAR(n_count, len, low, man);
    return 0;
}
220Volt вне форума Ответить с цитированием
Старый 14.09.2013, 20:36   #6
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Выглядит не очень, но юзабельно, вроде бы. Замечательно.
В репу не могу ниче кинуть ((.
rrrFer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Variadic templates 220Volt Общие вопросы C/C++ 2 16.05.2013 07:42
variadic templates и компиляторы _Bers Общие вопросы C/C++ 4 18.01.2013 09:55
Variadic Templates и их применение в качестве списка полей Пепел Феникса Общие вопросы C/C++ 9 13.08.2012 17:24
Macros Mylips Microsoft Office Excel 10 13.03.2009 18:05