Как заменить макрос на шаблонную функцию? - PullRequest
2 голосов
/ 03 декабря 2010

У меня есть макрос:

#define TWO_CMD( c1, c2 ) { const long r1=c1; if ( r1 ) return r1; return c2; }

и использование:

long MyClass::SomeFunc( long a )
{
    //...
    if ( a )
        TWO_CMD( Func<int>(a), Func<void>() );
    else
        TWO_CMD( Func<double>(), Func<std::string>(a) );
    //...
}

Func - это функции-члены шаблона.Но ключевым требованием является сохранение читабельности кода!

Я предполагаю, что есть вариант с функцией-членом шаблона, который имеет указатель на функции-члены в качестве аргументов:

return two_cmd( Func<int>, a, Func<void> );

Но этот синтаксисне ясно.

Ответы [ 3 ]

4 голосов
/ 03 декабря 2010

Первым делом: скрыть инструкцию возврата внутри макроса - это зло. Когда кто-то смотрит на эту функцию, совсем не ясно, что эти вызовы TWO_CMD фактически вызывают возврат функции.

Самый простой способ сделать это - передать вызываемые объекты в шаблон функции и вернуть ему результат:

template <typename R, typename F, typename G>
R Evaluate(const F& f, const G& g) {
    R x = f();
    return x ? x : g();
}

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

return Evaluate<long>(
    std::bind(&MyClass::Func<int>, this, a), 
    std::bind(&MyClass::Func<void>, this));

return Evaluate<long>(
    std::bind(&MyClass::Func<double>, this), 
    std::bind(&MyClass::Func<std::string>, this, a));

Если ваш компилятор и стандартная библиотека не поддерживают C ++ 0x или C ++ TR1 bind, в Boost есть реализация, которая почти идентична.

(Я назвал функцию Evaluate, потому что я не могу придумать хорошее название для этой функции.)

2 голосов
/ 03 декабря 2010

Хм, конечно, это довольно тривиально? Какой смысл слишком усложнять? Я думаю, что код ниже довольно легко понять - зачем его скрывать?

long res = 0;
if ( a )
    return (res = Func<int>(a)) ? res : Func<void>();
else
    return (res = Func<double>()) ? res : Func<std::string>(a);

Упс, было больше () из более раннего != 0 теста

0 голосов
/ 04 августа 2016

Мой ответ не касается непосредственно вопроса, а лишь некоторых наблюдений:

  1. Я бы рекомендовал минимизировать множественные точки возврата в функции в целом, чтобы упростить поток кода. В данном случае это простой пример, но операторы return в произвольных местах внутри функции могут быть пропущены при внесении изменений, что приводит к ошибкам.

    Я склонен придерживаться одного оператора возврата в конце, т.е. одна точка входа и одна точка выхода. Это заставляет вас писать более простые функции с одной целью и перемещать подоперации в подфункции.

  2. Стоит думать нестандартно при формировании структуры кода. В этом случае, есть ли другой более простой способ сформулировать проблему? Рассмотрим шаблоны проектирования. Необходимость написать какой-то неуклюжий макрос или шаблон может указывать на структурную проблему, которая может быть решена путем дополнительного анализа проблемы в целом.

  3. В вашем примере, если a равно 0 (единственное значение, дающее в выражении ложное значение), Func<std::string>(a) [потенциально] является константой.

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