c ++ # определить макрос в скобках? - PullRequest
8 голосов
/ 17 апреля 2009

Вместо того, чтобы делать следующее каждый раз

start();

// some code here

stop();

Я хотел бы определить какой-то макрос, который позволяет писать так:

startstop()
{

//code here

}

Возможно ли это в C ++?

Ответы [ 9 ]

41 голосов
/ 17 апреля 2009

Вы можете сделать что-то очень близкое, используя небольшой вспомогательный класс C ++.

class StartStopper {
public:
    StartStopper() { start(); }
    ~StartStopper() { stop(); }
};

Тогда в вашем коде:

{
    StartStopper ss;
    // code here
}

Когда выполнение входит в блок и создает переменную ss, вызывается функция start(). Когда выполнение покидает блок, автоматически вызывается деструктор StartStopper, а затем вызывается stop().

14 голосов
/ 17 апреля 2009

Идиоматический способ сделать это в C ++ называется Получение ресурсов - это инициализация , или коротко RAII. В дополнение к предоставлению того, что вы хотите, он также имеет дополнительное преимущество, заключающееся в безопасности исключений: функция stop будет вызываться, даже если ваш код вызывает исключение.

Определить структуру охраны:

struct startstop_guard
{
    startstop_guard()
    {
        start();
    }
    ~startstop_guard()
    {
        stop();
    }
};

, а затем переписать код следующим образом:

{
    startstop_guard g;
    // your code
}

Деструктор охраны (и, следовательно, функция stop) будет вызываться автоматически в конце окружающего блока.

6 голосов
/ 17 апреля 2009

Другие ответы хорошо рассмотрели RAII-сторону вопроса, поэтому Я собираюсь рассмотреть синтаксическую сторону вопроса .

#define startstop for(Starter s; s.loop; s.loop = false)
struct Starter {
    bool loop;
    Starter() { start(); loop = true; }
    ~Starter() { stop(); }
};

Используется как :

startstop {
    // some code
}

Должен быть достаточно понятным.

4 голосов
/ 17 апреля 2009
#define startstop(x, y, ...) for( /* use macro args */ )
2 голосов
/ 17 апреля 2009

Общее решение с RAII и boost :: function (std :: function).

class starter
{
    typedef boost::function< void () > action;
    action end_;
public:
    starter(action start, action end):
        end_(end)
    { 
        log("starter start");
        start(); 
    }
    ~starter()
    { 
        log("starter end");
        end_() ; 
    }
};
int main()
{
    {
        starter s(start, stop);
        middle();
    }

    return 0;
}

или проверить и проверить идею

    void print(const std::string& message)
    {
        std::cout << message << std::endl;
    }
    int main()
    {
        starter s(boost::bind(print, "globalstart"),
                  boost::bind(print, "globalend")); 

        {
            starter s(boost::bind(print, "start"),
                      boost::bind(print, "end")); 
            std::cout << "middle" << std::endl;
        }
        return 0;
    }
1 голос
/ 26 июля 2010

благодарность за идею .. Я думал, что заполнил остальное в

#define startstop() for(start();isStarted();stop())

1 голос
/ 17 апреля 2009

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

1 голос
/ 17 апреля 2009

Что вы пытаетесь сделать? Я бы порекомендовал проверить RAII как способ, более ориентированный на C ++, чем взлом макросов со всеми непредвиденными последствиями.

0 голосов
/ 18 апреля 2009

В c # вы можете использовать шаблон IDisposable и реализовать свою функцию Stop () в методе Dispose (), но это будет работать, если вы используете вариант .net c ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...