我想用 boost
中更通用的东西替换 SomeFunction
和 SetArg
。
看起来可以用 bind
结合 lambda
来完成,但我不知道怎么做。
这段代码非常简单,但我想替换它的原因是因为我需要一个用于 2
和 3
等参数。
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/