Discussion:
a recursive function type
(too old to reply)
Aleksey Demakov
2018-09-12 22:30:00 UTC
Permalink
Hi all,

I need a std::function<> that returns a std::function<> of the same type. I
was able to find the following solutions to this problem:

https://stackoverflow.com/questions/23737449/recursive-typedef-function-definition-stdfunction-returning-its-own-type
https://stackoverflow.com/questions/29397744/return-type-of-function-that-returns-an-stdfunction
https://stackoverflow.com/questions/48066747/c-recursive-function-type

I liked one of the answers better than the others but still I was not
totally happy. However it occured to me that it is possible to improve (I
believe) upon it. And I came up with this one:

struct state : public std::function<state()> {
using base = std::function<state()>;
using base::base;
};

As I'm far from being a C++ expert so 'm not sure if there any flaws with
this approach. Could it yet be improved? A very simple test (see below) I
tried with g++ appears to work.

Regards,
Aleksey

#include <functional>
#include <iostream>

struct state : public std::function<state()>
{
using base = std::function<state()>;
using base::base;
};

struct functor
{
state operator()() {
std::cout << "functor\n";
return {};
}
};

state function() {
std::cout << "function\n";
return [] {
std::cout << "lambda\n";
return functor();
};
}

int main()
{
state s(&function);
do s = s(); while(s);
return 0;
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Tony V E
2018-09-13 02:45:45 UTC
Permalink
<html><head></head><body lang="en-US" style="background-color: rgb(255, 255, 255); line-height: initial;"> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">I asked the same thing on twitter, got basically the same answer</div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">.</div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-size: initial; line-height: initial; text-align: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif;">https://mobile.twitter.com/bjorn_fahller/status/895938729482883072?p=v</span></div><div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><span style="font-size: initial; line-height: initial; text-align: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif;"><br></span></div> <div style="width: 100%; font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);"><br style="display:initial"></div> <div style="font-size: initial; font-family: Calibri, 'Slate Pro', sans-serif, sans-serif; color: rgb(31, 73, 125); text-align: initial; background-color: rgb(255, 255, 255);">Sent&nbsp;from&nbsp;my&nbsp;BlackBerry&nbsp;portable&nbsp;Babbage&nbsp;Device</div> <table width="100%" style="background-color:white;border-spacing:0px;"> <tbody><tr><td colspan="2" style="font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"> <div style="border-style: solid none none; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding: 3pt 0in 0in; font-family: Tahoma, 'BB Alpha Sans', 'Slate Pro'; font-size: 10pt;"> <div><b>From: </b>Aleksey Demakov</div><div><b>Sent: </b>Wednesday, September 12, 2018 6:30 PM</div><div><b>To: </b>ISO C++ Standard - Discussion</div><div><b>Reply To: </b>std-***@isocpp.org</div><div><b>Subject: </b>[std-discussion] a recursive function type</div></div></td></tr></tbody></table><div style="border-style: solid none none; border-top-color: rgb(186, 188, 209); border-top-width: 1pt; font-size: initial; text-align: initial; background-color: rgb(255, 255, 255);"></div><br><div id="_originalContent" style=""><div dir="ltr">Hi all,<br><br> I need a std::function&lt;&gt; that returns a std::function&lt;&gt; of the same type. I was able to find the following solutions to this problem:<br><br><a href="https://stackoverflow.com/questions/23737449/recursive-typedef-function-definition-stdfunction-returning-its-own-type">https://stackoverflow.com/questions/23737449/recursive-typedef-function-definition-stdfunction-returning-its-own-type</a> <br><a href="https://stackoverflow.com/questions/29397744/return-type-of-function-that-returns-an-stdfunction">https://stackoverflow.com/questions/29397744/return-type-of-function-that-returns-an-stdfunction</a> <br><a href="https://stackoverflow.com/questions/48066747/c-recursive-function-type">https://stackoverflow.com/questions/48066747/c-recursive-function-type</a> <br><br>I liked one of the answers better than the others but still I was not totally happy. However it occured to me that it is possible to improve (I believe) upon it. And I came up with this one:<br><br><div>struct state : public std::function&lt;state()&gt;
{</div><div>&nbsp; using base = std::function&lt;state()&gt;;</div><div>&nbsp; using base::base;</div><div>};</div><br>As I'm far from being a C++ expert so 'm not sure if there any flaws with this approach. Could it yet be improved? A very simple test (see below) I tried with g++ appears to work.<br><br>Regards,<br>Aleksey<br> <br>#include &lt;functional&gt;<br>#include &lt;iostream&gt;<br><br>struct state : public std::function&lt;state()&gt;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using base = std::function&lt;state()&gt;;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using base::base;<br>};<br><br>struct functor<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; state operator()() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "functor\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>};<br><br>state function() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "function\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return [] {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "lambda\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return functor();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>}<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; state s(&amp;function);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do s = s(); while(s);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br> </div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br>
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br>
Visit this group at <a href="https://groups.google.com/a/isocpp.org/group/std-discussion/">https://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br>
<br><!--end of _originalContent --></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Discussion&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-discussion+***@isocpp.org">std-discussion+***@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-***@isocpp.org">std-***@isocpp.org</a>.<br />
Visit this group at <a href="https://groups.google.com/a/isocpp.org/group/std-discussion/">https://groups.google.com/a/isocpp.org/group/std-discussion/</a>.<br />
Richard Smith
2018-09-13 22:28:06 UTC
Permalink
Post by Aleksey Demakov
Hi all,
I need a std::function<> that returns a std::function<> of the same type.
https://stackoverflow.com/questions/23737449/recursive-typedef-function-definition-stdfunction-returning-its-own-type
https://stackoverflow.com/questions/29397744/return-type-of-function-that-returns-an-stdfunction
https://stackoverflow.com/questions/48066747/c-recursive-function-type
I liked one of the answers better than the others but still I was not
totally happy. However it occured to me that it is possible to improve (I
struct state : public std::function<state()> {
using base = std::function<state()>;
using base::base;
};
As I'm far from being a C++ expert so 'm not sure if there any flaws with
this approach. Could it yet be improved?
Generally, C++ (like many, perhaps most, other languages) supports
isorecursive types but not equirecursive types:

struct A {
A *next; // ok, isorecursive
};
using T = T*; // error, equirecursive

struct B {
std::function<B()> next; // ok, isorecursive
};
using U = std::function<U()>; // error, equirecursive

The canonical and typical solution when you want a recursive type is to
introduce a level of indirection, that is, to use an isorecursive type
instead of an equirecursive type. That's what your 'struct state' is. So:
your workaround seems to be the right thing.

You can write it more tersely / less repetitively as:

struct state : std::function<state()> {
using function::function;
};

A very simple test (see below) I tried with g++ appears to work.
Post by Aleksey Demakov
Regards,
Aleksey
#include <functional>
#include <iostream>
struct state : public std::function<state()>
{
using base = std::function<state()>;
using base::base;
};
struct functor
{
state operator()() {
std::cout << "functor\n";
return {};
}
};
state function() {
std::cout << "function\n";
return [] {
std::cout << "lambda\n";
return functor();
};
}
int main()
{
state s(&function);
do s = s(); while(s);
return 0;
}
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Continue reading on narkive:
Loading...