Enforce exact invokable signature in C++
i have a function that takes an invokable, and i want to make sure that the signature of the passed invokable is exactly the specified one.
#include <type_traits>
#include <cassert>
#include <iostream>
template<typename F>
requires std::is_invocable_v<F, float&>
float fn(F&& f) {
float v;
f(v);
return v;
}
int main() {
float v = 17.0;
std::cout << "v=" << v << std::endl; // returns v=17
float v2 = fn([&v](float& b){
b = v;
});
std::cout << "v2=" << v2 << std::endl; // returns v2=17
float v3 = fn([&v](float b){
b = v;
});
std::cout << "v3=" << v3 << std::endl; // returns some random value (uninitialized)
return 0;
}
https://godbolt.org/z/T7xGsqzvn
Here v3 is left uninitialized because the lambda takes the argument by value instead of a reference.
My question is now, how can i make sure that an invokable passed to fn always takes by reference, co my code works.
Thank you.
Solution 1:
You may add another constraint to fn
:
template<typename F>
requires std::is_invocable_v<F, float&>
and (not std::is_invocable_v<F, float>) // <--
float fn(F&& f) {
//...
}
Live here.