Создание функции с препроцессором и прототипом указателя на функцию

Я хочу раз и навсегда создать красивую и блестящую версию этого моков для кода C< /а>.

Я хочу создать макрос котла, как показано ниже:

#define MOCK_FREE_FUNCTION(NAME, SIGN, MOCK) \
  /* whatever goes here */

В коде (или заголовке) это должно использоваться так: MOCK_FREE_FUNCTION2(myFunc, void(char *, const char *), myFuncMock); и расширяться во что-то

struct Whatever_myFunc {
  MOCK_CONST_METHOD2(myFunc, void (char *x, char *y));
};

Whatever_myFunc myFuncMock;

extern "C" {
   void myFunc(char *x, char *y) {
      myFuncMock.(x,y);
   }
}

/* maybe some convenience EXPECT_CALL thing */

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

Дополнение из комментария

генерировать большую часть материала легко, проблема, которую я не могу решить, заключается в том, как gmock удается получить от

MOCK_METHOD2(foo, void(char *, char*)

что-то вроде void foo(char *, char*)

Это самое близкое, что я мог придумать:

#include <stdio.h>

#define MOCK_FREE_FUNCTION2(NAME, MOCK, RET, ARGS) \
  typedef RET (*NAME ## Type) ARGS; \
  NAME ## Type NAME = barfoo_f;

/* ok it's callable, but how do I get my own code inside here? */
void barfoo_f(int i, int j) {
  printf ("hello world %d %d\n", i, j);
}

// How does google mock get rid of , in the prototype
MOCK_FREE_FUNCTION2(FooBar, XXX, void, (int,int));

int main(int argc, char **argv) {
  FooBar(1,2);
}

person Alexander Oh    schedule 15.04.2014    source источник
comment
Пожалуйста, покажите свою попытку, чтобы мы могли помочь вам исправить ее.   -  person Barmar    schedule 15.04.2014
comment
@Barmar: вот кое-что. Я не понял, как мне втиснуть свой собственный код. И я понятия не имею, как я могу на самом деле передать подпись, похожую на google-mock, при этом расширяясь до чего-то, что компоновщик примет как символ.   -  person Alexander Oh    schedule 15.04.2014


Ответы (1)


Возможный способ решения вашей непосредственной проблемы (как перейти от MACRO(foo, void(char*, char*)) к void foo(char*, char*)) может заключаться в сочетании с функциональными чертами:

template <typename F>
struct func_traits;

template <typename R, typename... Args>
struct func_traits<R(Args...)>
{
    using return_type = R;

    template <size_t I>
    using arg_type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};

#define MACRO_2(NAME, TYPE)                                                  \
    func_traits<TYPE>::return_type NAME(func_traits<TYPE>::arg_type<0> arg0, \
                                        func_traits<TYPE>::arg_type<1> arg1)

(Я просто использую std::tuple как быстрый способ реализовать здесь списки типов.)

person Oktalist    schedule 15.04.2014