c++ - 如何转发未命名的函数参数

标签 c++ c++17

因此,我正在尝试为我的虚拟类函数创建一个模拟宏。
这是带有一个模拟函数的模拟类的示例。 (这按预期工作)

class MockEnvironment : public IEnvironment {
public:
    using runType = int(std::string program,
                        std::vector<std::string> arguments);

    MockedFunction<runType> runMock = MockedFunction<runType>("run");

    int run(std::string program, std::vector<std::string> arguments) override {
        return runMock(program, arguments);
    }

    //    MOCK_METHOD(int, run, (std::string, std::vector<std::string>)); // this is the goal
};

MockedFunction是带有operator()的类,应在调用函数时调用该类。
我的目标是将函数包装在宏中,以便能够模拟任何函数。您可能会看到的问题是,在泛化时,我将需要处理带有未命名参数的函数。

#define MOCK_METHOD(ret, name, args)                                           \
    MockedFunction<ret(args)> mocked_##name =                                  \
        MockedFunction<ret(args)>(#name);                                      \
    ret name##Mock(args) { /* how to solve? */ }

// This would expand to something like
MockedFunction<...> runMock = MockedFunction<...>("run"); // More detailed in above example

int run(std::string, std::vector<std::string>) override {
    return runMock(/*how to forward the arguments when they do not have names?*/)
}
我曾考虑过使用某种可变文本模板,但是还没有找到任何使它工作的方法。我也曾尝试阅读谷歌的模拟实现,但我很难看到他们如何解决它。
所以我的问题很简单。如何将run中参数的内容移动到要调用的函数?
我最多可以使用c++ 17。我确实意识到,如果在宏中指定需要多少个参数,会更容易,但是,如果可以解决更一般的示例,那将是最佳选择。
编辑:
如果我事先知道参数的数量,这是我想出的最好的方法。
#define INTERNAL_MOCK_METHOD_COMMON(ret, name, args)                           \
    using name##T = ret(args);                                                 \
    unittest::MockedFunction<ret(args)> mock_##name =                          \
        unittest::MockedFunction<ret(args)>(#name);

#define MOCK_METHOD(ret, name)                                                 \
    INTERNAL_MOCK_METHOD_COMMON(ret, name, ())                                 \
    ret name() {                                                               \
        return mock_##name();                                                  \
    }

#define MOCK_METHOD1(ret, name, args)                                          \
    INTERNAL_MOCK_METHOD_COMMON(ret, name, args)                               \
    ret name(typename unittest::MockedFunction<name##T>::ArgT<0>::type a) {    \
        return mock_##name(a);                                                 \
    }

#define MOCK_METHOD2(ret, name, args)                                          \
    INTERNAL_MOCK_METHOD_COMMON(ret, name, args)                               \
    ret name(typename unittest::MockedFunction<name##T>::ArgT<0>::type a,      \
             typename unittest::MockedFunction<name##T>::ArgT<1>::type b) {    \
        return mock_##name(a, b);                                              \
    }

// ...

template <typename T>
class MockedFunction {};

template <typename ReturnT, typename... ArgsT>
class MockedFunction<ReturnT(ArgsT...)> {
public:
    // Return argument type at the specified index
    template <int i>
    struct ArgT {
        using type = typename std::tuple_element_t<i, std::tuple<ArgsT...>>;
    };
然后可以像这样使用

class IObject {
public:
    virtual int update() = 0;
    virtual void setValue(int) = 0;
};

class MockObject : public IObject {
public:
    MOCK_METHOD(int, update);
    MOCK_METHOD1(void, setValue, (int));
};
需要说明的是:不必用数字指定参数的数量会很好。

最佳答案

您不能使用未命名的参数。您可以考虑命名它们,也许像这样:

#define MOCK_METHOD(ret, name, args, names)                                           \
    MockedFunction<ret(args)> mocked_##name =                                  \
        MockedFunction<ret(args)>(#name);                                      \
    ret name##Mock(args) { return runMock names; }

MOCK_METHOD(int, run, (std::string s, std::vector<std::string> v), (s, v));

关于c++ - 如何转发未命名的函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64087151/

相关文章:

c++ - 函数模板与重载混合

C++:如何管理对象生命周期和依赖关系?

c++ - 从模板函数返回匿名结构(用于结构化绑定(bind))

C++ 序列点和 C++17 中求值顺序的变化

c++ - 为什么最负的 int 值会导致模棱两可的函数重载错误?

C++ 和 Swift 彼此不喜欢

c++ - 从单线程到多线程图像处理

c++ - 从异构列表中提取数据

c++ - 私有(private)静态成员 - 编译错误?

c++ - gcc - 如何在结构定义中组合 __attribute__((dllexport)) 和 [[nodiscard]]?