I'm trying to verify at compile time if a given lambda accepts a certain type (double in the case of my example code). As long as the signature of the lambda explicitly specifies the types this works. However, as soon as I use a generic lambda with auto in the signature, I get compilation errors when evaluating the requires statement.
The following code snippet illustrates the problem (also on compiler explorer)
#include <concepts>
#include <iostream>
#include <string>
template<typename F>
concept accepts_double = requires(F f, double d) { f(d); };
struct Component{};
int main(){
auto f1 = [](double a){double b = a;};
auto f2 = [](std::string a){std::string b = a;};
auto f3 = [](auto a){std::string b = a;};
std::cout << std::boolalpha << accepts_double<decltype(f1)> << "\n"; // expected true
std::cout << std::boolalpha << accepts_double<decltype(f2)> << "\n"; // expected false
//This one gives the error:
std::cout << std::boolalpha << accepts_double<decltype(f3)> << "\n"; // expected false, gives compilation error
}
I was under the impression that the requires statement would verify that f(d); was a valid expression and would return false if it was not. However, when compiling with the latest gcc and clang I get an error indicating that it is trying to evaluate the function body:
:13:38: error: no viable conversion from 'double' to 'std::string' (aka 'basic_string<char>')
My question Is there a different way to ensure that a lambda can be passed a double or are the requires statements restricted to checking the signature only?