constexpr lambda to function pointer conversion

65 views
Skip to first unread message

David W

unread,
Jun 27, 2015, 12:45:42 PM6/27/15
to std-dis...@isocpp.org
Hello,

I have a question about converting non-capturing lambdas to function pointers at compile time.

Section 5.1.2.6 of the current working draft (N4431) describes the function pointer conversion for non-capturing lambdas as "...a public non-virtual non- explicit const conversion function to pointer to function...".

Is there a reason that this conversion could not be constexpr as well? This would allow for tables of non-capturing lambdas to be initialized at compile time and placed in read-only data sections.
I haven't been able to find any discussion about why this is not allowed (or should not be allowed). I did find a possible workaround (http://pfultz2.com/blog/2014/09/02/static-lambda/), but it is somewhat messy.

Clang already optimizes the following definition into a read only section when compiling with -O2. ARM GCC 4.9 however, does not (it optimizes the conversion function to a constant address, but leaves the code to copy the addresses to the final array at a runtime). And neither compiler attempts to compute the table at compile time with default optimization levels.

extern int(* const functions[])() = {
[] { return 12;},
[] { return 31;},
[] { return 46;},
[] { return 79;},
[] { return 5;},
};

Any insight would be most welcome.

Thanks,
David

Ville Voutilainen

unread,
Jun 27, 2015, 12:47:06 PM6/27/15
to std-dis...@isocpp.org
On 27 June 2015 at 19:45, David W <dlwi...@newcommunities.net> wrote:
> Hello,
>
> I have a question about converting non-capturing lambdas to function
> pointers at compile time.
>
> Section 5.1.2.6 of the current working draft (N4431) describes the function
> pointer conversion for non-capturing lambdas as "...a public non-virtual
> non- explicit const conversion function to pointer to function...".
>
> Is there a reason that this conversion could not be constexpr as well? This

Some, like "we didn't want to go there at that time". However, things
are hopefully
going to improve:

http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4487.pdf

David Krauss

unread,
Jul 3, 2015, 12:02:21 AM7/3/15
to std-dis...@isocpp.org

On 2015–06–28, at 12:07 AM, DavidW <dlwi...@newcommunities.net> wrote:

Clang already optimizes the following definition into a read only section when compiling with -O2. ARM GCC 4.9 however, does not (it optimizes the conversion function to a constant address, but leaves the code to copy the addresses to the final array at a runtime). And neither compiler will attempt to compute this table at compile time at default optimization levels.

This is a very tricky optimization, because initializing a global with a non-constant expression is a side effect. Hoisting it into ROM requires proving that the zero-initialized state was never observed.

Clang doesn’t apply the optimization to this program (but does if fn0 is removed):

extern int(* const functions[])(); // Forward declaration.
// functions[] is zero-initialized here.

int (*fn0)() = * (int (* const volatile *)()) functions; // read a nullptr

extern int(* const functions[])() = {
[] { return 12;},
[] { return 31;},
[] { return 46;},
[] { return 79;},
[] { return 5;},
};
// now functions[] is filled with values.

int main() {
    assert ( fn0 == nullptr ); // OK! Congratulations, Clang!
}

At a more practical level, constexpr lambdas are a fairly high priority for C++17: http://open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4487.pdf — see §3.4.

dlwi...@newcommunities.net

unread,
Jul 3, 2015, 9:43:09 AM7/3/15
to std-dis...@isocpp.org
Thanks both of you. I'm glad to hear that this is on track for C++17. I've been hoping someone would create a proposal for this, so it's good to know that there is one now. I'll be following its progress (and hoping compilers implement it in their "C++1z" mode quickly).
Reply all
Reply to author
Forward
0 new messages