Using C++17, I have a method that takes a function with a parameter that must be a reference. Right now, I do not get a compilation error when I pass a lambda taking a non-reference parameter. I want this situation to not compile.
How can I achieve this? Also which implicit conversion kicks in and causes the not intended code to compile?
#include <iostream>
#include <functional>
using namespace std;
void
takesRefLambda (function < void (string & t) > f)
{
string test = "nope";
f (test);
cout << test << endl;
}
int
main ()
{
//this shall fail at compile time, as parameter `q` is not a reference
takesRefLambda ([&](string q)
{
q = "yep1";
});
//this shall compile
takesRefLambda ([&](string & q)
{
q = "yep2";
});
return 0;
}
std::function is designed to be maximally flexible, converting any arguments as necessary. This is usually what you want with type-erasure after all.
The conversions std::function performs are straightforward. Given your signature void(std::string&), std::function::operator() is more or less
void operator()(std::string& s)
{
callable(s);
}
Which is obviously valid if callable accepts a std::string.
If you must have an exact function signature, test for it
template<typename C>
void test(void (C::*) (std::string&));
template<typename C>
void test(void (C::*) (std::string&) const);
template<typename F>
auto takesRefLambda(F&& f)
-> decltype(test<std::decay_t<F>>(&std::decay_t<F>::operator()))
{
// use f
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With