Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why cant we declare std::function with auto

I got following code:

 template<typename T>
concept con1 = requires(T t, std::string s){
    { t[s] } -> std::same_as<std::string>;
};

using function_signature = std::function<void ( con1 auto  functor)>; // ERROR!

while the compiler has no problem me defining the lambda directly:

auto lambda_1 = [](con1 auto functor){....} 

The reason why I want the former to work is the following:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 template<std::semiregular T>
 class R{

     T functor;
     R() = default;
     register_functor(T functor_) { functor = std::move(functor_);}
  }

If I get to instantiate my class using the signature like:

  auto rr = R<function_signature>(); 

I can get to register my functor at a later stage, and even change the function at run time as long as I keep the signature the same. Using the lambda directly means I am stuck with whatever my lambda is at the time I instantiate the class R

>Solution :

auto in a lambda parameter list doesn’t represent one single automatically-inferred type like it would in a variable initialization, it represents that the lambda has a templated operator() which has a whole parameterized family of function signatures.

You can’t instantiate a template that expects a concrete type (and std::function does) with a parameterized family of types. You could create a parameterized family of typedefs, each formed by instantiating std::function:

template<con1 T> using function_signature = std::function<void (T)>;

But this doesn’t get you any closer to being able to write R<function_signature>. For that, you’d need template<template class T<U>> class R; and then R needs to somehow provide the type parameter T2 in T<T2> functor.

In the end, it comes down to std::function being a wrapper to a pointer-to-member function (among other flavors), and a pointer-to-member function cannot point to a whole template family of member functions.

This also fails:

auto lambda_1 = [](con1 auto functor){....};
auto pmf = &lambda_1::operator(); // cannot take address of template member function

Put another way, type-erasure doesn’t work on templates. Instantiating the template requires its type.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading