The following example fails to compile as soon as the lambda capture any variable. If the capture is removed the compiler will successfully compile the code below.
#include <concepts>
#include <functional>
#include <iostream>
template<typename T>
concept OperatorLike = requires(T t, std::string s) {
{ t[s] } -> std::same_as<std::string>;
};
template<typename T, typename O>
concept Gettable = requires(T t, O op) {
t.apply_post(0, op); };
template<std::semiregular F>
class RestApiImpl {
F m_post_method;
public:
RestApiImpl(F get = F{}) : m_post_method{std::move(get)} {}
template<OperatorLike IF>
requires std::invocable<F, const int, IF>
void apply_post(const int req, IF interface){
m_post_method(req, std::move(interface));
}
};
int main(){
int ii;
auto get = [&ii](int, OperatorLike auto intf){
std::string dummy = "dummy";
std::cout << intf[dummy];
};
RestApiImpl api(get);
return 0;
};
If the lambda function get() has empty brackets [] , meaning no capture it will compile.
The need of the class RestApiImpl
is based on following application:
class Server{
public:
struct impl;
void run(Gettable<impl> auto& api){
api.apply_post(0, impl(*this));
}
struct impl {
public:
Server& m_server;
impl(Server& server ) : m_server(server){}
std::string operator[](std::string key) {
return "dummy_for_now";
}
};
};
int main(){
auto get = [&ii](int, OperatorLike auto intf){
std::string dummy = "dummy";
std::cout << intf[dummy];
};
RestApiImpl api(get);
Server server;
server.run(api);
return 0;
};
The error message:
:35:24: error: class template argument deduction failed: 35 | RestApiImpl api(get); | ^ :35:24: error: no matching function for call to 'RestApiImpl(main()::&)' :18:5: note: candidate: 'template RestApiImpl(F)-> RestApiImpl' 18 | RestApiImpl(F get = F{}) : m_post_method{std::move(get)} {} | ^~~~~~~~~~~ :18:5: note: template argument deduction/substitution failed: : In substitution of 'template RestApiImpl(F)-> RestApiImpl [with F = main()::]': :35:24: required from here :18:5: error: template constraint failure for 'template requires semiregular class RestApiImpl' :18:5: note: constraints not satisfied
What options to I have in terms of overcoming this ?`
CodePudding user response:
std::semiregular
requires both std::copyable
and std::default_initializable
.
std::copyable
means that it requires the type to be copy-constructible and copy-assignable.
std::default_initializable
means that it requires the type T
to have well-formed initializations of the forms T t;
, T()
and T{}
.
A lambda with a capture has a deleted copy assignment operator, no move assignment operator and no default constructor, while for a capture-less lambda (since C 20) all of them are defaulted. As a consequence a lambda with capture is not std::copyable
(or std::movable
for that matter) and not std::default_initializable
and so especially also not std::semiregular
, while a capture-less lambda is all of these.
Your RestApiImpl
requires that the passed argument for F get
in the constructor be std::semiregular
.
To resolve this rethink whether RestApiImpl
really requires all of these properties of the type.
I can see that it requires move-constructibility in m_post_method{std::move(get)}
, but it is unclear where it uses e.g. copy-assignability from what you are showing.
= F{}
uses default-constructibility, but that default value is not used or instantiated if you are not default-constructing a RestApiImpl
instance with that type.
Then use concepts which are not as restrictive as std::semiregular
.
If that is not a possibility, then you cannot use a lambda like this directly. Instead you can use an old-style functor type, e.g. a class with overloaded operator()
and have it store a std::reference_wrapper<int>
to the ii
object. This assures assignability, because a simple reference as member would make the class non-assignable.
CodePudding user response:
If you capture ii
by reference, the lambda is neither default constructible nor copyable. The std::semiregular
concept requires this tough.
The template parameter deduced for RestApiImpl
does not fulfill the requirements imposed on it.