EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: westfw on September 26, 2019, 09:55:57 am

Title: C++ "constexpr" function arguments
Post by: westfw on September 26, 2019, 09:55:57 am
So, C++ has constexpr "variables" and "functions."
Does it have an equivalent for function ARGUMENTS?
Ideally, I'd like to have overloaded functions:void foo(constexpr int bar) { ... }

void foo(int bar) { ... }
so that if I call foo() with a compile-time constant as an argument, it would invoke the first code, and if it wasn't, it would invoke the second...
(Yeah, I'm aware that I can do about the same thing using __builtin_constant_p(), at least with gcc.  But that tends to be ugly, and not portable, and it seems like the sort of thing  that would get standardized, eventually.)
Title: Re: C++ "constexpr" function arguments
Post by: ledtester on September 26, 2019, 01:11:27 pm
Doesn't seem possible at the moment, but there is a proposal in the works:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1045r0.html (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1045r0.html)


Here's a discussion on implementing is_constexpr() function for C++2a:

https://stackoverflow.com/questions/55288555/c-check-if-statement-can-be-evaluated-constexpr (https://stackoverflow.com/questions/55288555/c-check-if-statement-can-be-evaluated-constexpr)


Here's an old SO discussion of the problem:

https://stackoverflow.com/questions/8936549/constexpr-overloading (https://stackoverflow.com/questions/8936549/constexpr-overloading)

At that time looks like the best way to discriminate based on a constexpr parameter was to write a macro which called one implementation or another based on the return value of __builtin_constant_p().

Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on September 26, 2019, 03:09:27 pm
Just a thought or question about that...

As I get it, constexpr represents expressions that can be fully evaluated statically (at compile-time).
I guess obviously any litteral, or a combination thereof, is a constexpr. But there are possibly many other, more subtle cases, in which some expression can actually be fully evaluated statically, whereas it's really NOT obvious to the eye of the programmer. In that case, isn't using constexpr potentially very slippery, especially if you're making assumptions on what a constexpr is, and implements functions that act differently for constexpr parameters (something not currently available, and I guess, what I just said was probably part of the discussions?)

Overloaded functions can be so slippery already.
Title: Re: C++ "constexpr" function arguments
Post by: ledtester on September 26, 2019, 04:00:12 pm
The consensus seems to be that constexpr evaluation is Turing-complete:

https://github.com/llvm-mirror/clang/blob/master/test/SemaCXX/constexpr-turing.cpp

In C++11 it wasn't, but apparently it has since been fixed:

https://stackoverflow.com/questions/9201506/is-constexpr-based-computation-turing-complete/9528554#9528554

Template meta-programming is also Turing-complete so now there are two ways to hang your compiler.
Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on September 26, 2019, 07:18:44 pm
(...)
Template meta-programming is also Turing-complete so now there are two ways to hang your compiler.

Good lord. :-DD

Someday someone will write a full graphics Tetris game intended to run at compile-time inside a C++ compiler.
 ;D
Title: Re: C++ "constexpr" function arguments
Post by: magic on September 26, 2019, 08:01:37 pm
As I get it, constexpr represents expressions that can be fully evaluated statically (at compile-time).
I guess obviously any litteral, or a combination thereof, is a constexpr. But there are possibly many other, more subtle cases, in which some expression can actually be fully evaluated statically, whereas it's really NOT obvious to the eye of the programmer. In that case, isn't using constexpr potentially very slippery, especially if you're making assumptions on what a constexpr is, and implements functions that act differently for constexpr parameters (something not currently available, and I guess, what I just said was probably part of the discussions?)

Overloaded functions can be so slippery already.
There are constexpr variables and functions, and those are recognized by being marked as such. There are some criteria as to which functions are allowed to be constexpr, which guarantee that the function can actually be computed at compile time. Or so they did in C++11, anyway ;)
Not sure if such a thing as "a constexpr expression" is defined, but we could agree that any expression which doesn't refer to non-constexpr variables or functions "is constexpr". Then the concept is quite well defined, because constexpr variables and functions are well defined.

By the way, template instantiation cannot actually hang most compilers. They impose some limits (like 1000) on the depth of template instantiations.
Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on September 29, 2019, 04:01:22 pm
There are constexpr variables and functions, and those are recognized by being marked as such. There are some criteria as to which functions are allowed to be constexpr, which guarantee that the function can actually be computed at compile time. Or so they did in C++11, anyway ;)
Not sure if such a thing as "a constexpr expression" is defined, but we could agree that any expression which doesn't refer to non-constexpr variables or functions "is constexpr". Then the concept is quite well defined, because constexpr variables and functions are well defined.

My point was not that constexpr was not well defined. My point was explicitely about using constexpr in function parameters to write different overloaded methods (which apparently is not yet allowed, and that's why I think it makes sense that it's not), which is what the OP was willing to do.

Compilers will know what expressions can be compatible with constexpr (can be fully evaluated at compile-time), but my point was that it may NOT be as trivial for programmers, so that the programmer MAY not know which version of an overloaded function will be called in some particular situation. The OP's query was exactly where constexpr as parameters could become slippery to handle.

By the way, template instantiation cannot actually hang most compilers. They impose some limits (like 1000) on the depth of template instantiations.

There most likely is a limit, but is it documented? Can you point us to a reference for that for GCC for instance?
And then, as it's supposed to have become Turing-complete, can't there be some cases in which you could make definitions "loop" in some way without exceeding the max depth?
Title: Re: C++ "constexpr" function arguments
Post by: magic on September 29, 2019, 06:05:36 pm
Perhaps you are right, actually.

I looked up the details of what constitutes a "constant expression" at cppreference.com and while it starts reasonably (don't use non-const/uninitialized variables, don't call non-constexpr functions, don't pass non-constant arguments to functions, don't use anything declared but not defined, avoid UB) it quickly wanders into a hairy mess of rules about casting, inline assembly, implicit conversions,  ... :scared:

As for template depth in GCC, sure
Quote
-ftemplate-depth=n

    Set the maximum instantiation depth for template classes to n. A limit on the template instantiation depth is needed to detect endless recursions during template class instantiation. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than 17 (changed to 1024 in C++11). The default value is 900, as the compiler can run out of stack space before hitting 1024 in some situations.

Each template instantiation directly instantiates only some finite number of additional templates (as they occur in the definition) so to instantiate infinitely many templates you have to go infinitely deep. That being said, with fanout of 1000000 and 1000 levels depth there isn't much practical difference ;)
Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on September 29, 2019, 06:19:36 pm
1024 in C++11... that sounds already crazy. ;D

But as I said,  I additionally wonder whether there could be other ways of hanging the compilers than using recursive templates...
I'm not keen enough on all the possibilities for C++ metaprogramming...
Title: Re: C++ "constexpr" function arguments
Post by: ledtester on October 11, 2019, 06:52:52 pm
This just showed up... it goes over proposed extensions to the use of constexpr in function parameters including overloading:

https://youtu.be/bIc5ZxFL198?t=6m15s

Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on October 17, 2019, 04:50:11 pm
C++ makes me think more and more of some kind of "all you can eat" buffet...
 ::)
Title: Re: C++ "constexpr" function arguments
Post by: paullo on November 04, 2019, 02:02:40 pm
Someday someone will write a full graphics Tetris game intended to run at compile-time inside a C++ compiler.

Already been done :) https://blog.mattbierner.com/stupid-template-tricks-super-template-tetris/
Title: Re: C++ "constexpr" function arguments
Post by: SiliconWizard on November 04, 2019, 02:22:17 pm
Someday someone will write a full graphics Tetris game intended to run at compile-time inside a C++ compiler.

Already been done :) https://blog.mattbierner.com/stupid-template-tricks-super-template-tetris/

 :-DD