Reputation: 1697
I'm looking for a solution how I can create an interceptor/mock lambda to be able to check, whether it was called. What I tested was:
// test.hpp
template<typename R, typename ...Args>
std::function<R(Args&&...)> make_test_lambda(
bool &called,
std::function<R(Args&&...)> fn
) {
called = false;
return [&called, f=std::move(fn)](Args&&... args) {
called = true;
return f(std::forward<Args>(args)...);
};
}
// test.cpp: test with "catch"
bool called;
function_under_test(make_test_lambda(called, [](int x) {
REQUIRE(x == 4);
}));
REQUIRE(called);
It doesn't work no matching function for call
. Can you help me?
Thank you very much!
Upvotes: 1
Views: 784
Reputation: 16424
The problem is that every lambda has a unique type only known to the compiler. The template argument deduction takes place when compiler is selecting candidate functions, before determining the set of viable functions. Roughly speaking, a template function will be included in the candidate set, only if all the types can match exactly. Conversion is not allowed.
In your case, replacing your std::function<>
with a more generic template parameter Func is just ok. Like the following code:
template<class Func>
struct wrapper
{
wrapper(Func f, bool &called)
: f_(f)
, called_(called)
{}
template<class... Args>
decltype(auto)
operator() (Args&& ...args)
{
called_ = true;
return f_(std::forward<Args>(args)...);
}
private:
Func f_;
bool &called_;
};
template<class Func>
auto
make_test_lambda(bool &called, Func func)
{
called = false;
return wrapper<Func>(func, called);
}
Upvotes: 3