c++ - 如何创建一个修改其参数的函数对象?

标签 c++ boost googlemock

我想用 boost 中更通用的东西替换 SomeFunctionSetArg。 看起来可以用 bind 结合 lambda 来完成,但我不知道怎么做。

这段代码非常简单,但我想替换它的原因是因为我需要一个用于 23 等参数。

template<class T>
struct SomeFunction
{
    T value;
    SomeFunction(T s)
        : value(s) {}

    void operator()(T& s)
    {
        s = value;
    }
};

template<class T>
SomeFunction<T> SetArg(T value)
{
    return SomeFunction<T>(value);
}

要求:

  • 我想要一个返回函数对象的函数。
  • 当我调用这个函数对象时,参数通过引用传递。
  • 该函数通过将对象设置为预设值来修改通过引用传入的对象。
  • 在上面的代码中,预设值在ctor中按值传递,但任何其他方式也可以。

下面的代码演示了用法:

void main()
{
    std::string t;
    SetArg(std::string("hello"))(t);
    assert(t == "hello");
}

一些上下文:

我想测试 Foo 类的客户端代码。所以我想用我自己的实现替换 func1 的实现,但要以一种灵活的方式。

struct Foo
{
    virtual void func1(std::string& s)
    {
    }
};

struct MockFoo : public Foo {
    MOCK_METHOD1(func1, void(std::string&));
};

void ExampleTestCase::example()
{
  MockFoo f;
  std::string s;

  EXPECT_CALL(f, func1(_))
      .WillOnce(Invoke(SetArg(std::string("hello"))));

  f.func1(s);

  CPPUNIT_ASSERT_EQUAL(std::string("hello"), s);
}

调用接受一个函数或函数对象。在 func1 的新实现中,它调用 SetArg 返回的函数对象并将其参数设置为字符串 "hello"

Invoke 是 gmock/gtest 的一部分,但 SetArg 不是。

最佳答案

这是我想出的。 setter 的 operator() 可能会 需要一些调整,因为我们并没有真正从中受益 可能的移动语义在这里,但我现在无法弄清楚。

另请注意,这会大量使用 C++11 功能,而这些功能可能不会 可供您使用。

#include <string>
#include <iostream>
#include <tuple>

// set arbitrary values to 
template<typename... Args>
struct setter {
  // needed because we cannot use initializer lists as they require assignment
  setter(const std::tuple<Args&...>& t) : t(t) {}
  std::tuple<Args...> t;

  // again a template to trigger deduction again
  template<typename... Args2>
  void operator()(Args2&&... args) {
    t = std::make_tuple(args...);
  }
};

template<typename... Args>
setter<Args&...> create_setter(Args&... args) {
  return setter<Args&...>(std::tie(args...));
}

int main()
{
  int i = 0;
  long l = 1;
  std::string foo = "foo";

  auto s = create_setter(i, l, foo);

  s(23, 42, "bar");
  std::cout << i << std::endl;
  std::cout << l << std::endl;
  std::cout << foo << std::endl;

  return 0;
}

关于c++ - 如何创建一个修改其参数的函数对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7801236/

相关文章:

c++ - 我可以将 Boost Phoenix 表达式字符串化吗?

c++ - 如何使用 gmock 模拟构造函数和析构函数

c++ - 为什么在使用解除引用的指针时 EXPECT_CALL 测试意外通过?

c++ - Qt 模型测试,removeRows

c++ - 使用 jsoncpp 创建 JSON 字符串数组

c++ - NSData、NSDictionary、NSArray 等效项 C++

c++ - 无趣的模拟函数调用 bla() && 预期 : to be called at least once bla()?

c++ - c/c++ scanf/cin 从多行读取int

boost - 在应用程序的 WDK 构建环境中使用 boost?

c++ - 在 Windows 上从 1_55 更新到 1_62 后,创建一个 boost::asio::ip::udp::socket 在 LIB 中崩溃