我想将SomeFunction
和SetArg
替换为来自boost
的更通用的内容。
看起来可以使用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
Invoke接受一个函数或函数对象。在SetArg
的新实现中,它调用"hello"
返回的函数对象,并将其参数设置为字符串SetArg
。
Invoke是gmock / gtest的一部分,但{{1}}不是。
答案 0 :(得分:1)
这是我想出的。可能是operator()
的setter
需要一些调整,因为我们并没有真正受益于
可能会在这里移动语义,但我现在无法解决这个问题。
另请注意,这大量使用了可能没有的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;
}