Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

constexpr

38 views
Skip to first unread message

Doug Mika

unread,
Jun 15, 2015, 1:49:11 PM6/15/15
to
I will admit, I've tried to understand as precisely as possible what constexpr does. I think I have an idea, but I know it's not what it should be. So perhaps asking the following will further shed light on what constexpr does:

static_assert(100000<numeric_limits<int>::max(),"small ints!");

and then it says:
"Note that the second assert (only) works because numeric_limits<int>::max() is a constexpr function"

Can someone quickly explain why that is so?

Marcel Mueller

unread,
Jun 15, 2015, 1:58:35 PM6/15/15
to
Because the function is not yet compiled it cannot be called.
Furthermore it might be non deterministic. I.e. it is not clear whether
the assertion should fail or not. Think about cross compilation.


Marcel

Victor Bazarov

unread,
Jun 15, 2015, 1:58:49 PM6/15/15
to
Why WHAT is so? Next time be more specific please.

The requirement is that the first argument of 'static_assert' shall be a
constant-expression. If you try using any function that is not declared
'constexpr' in an expression, the compiler will refuse it. In your
example, the expression 100000 < blah, the 'blah' portion is a call to a
function declared 'constexpr', so the entire expression becomes constant
expression (calculated in compile-time).

If that's not what you were asking, rephrase your question.

V
--
I do not respond to top-posted replies, please don't ask

Richard

unread,
Jun 15, 2015, 2:50:18 PM6/15/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<53029355-0634-49cf...@googlegroups.com> thusly:
Ask yourself "What does static_assert do?"

Answer: "Performs compile-time assertion checking."
<http://en.cppreference.com/w/cpp/language/static_assert>

What does this imply? It implies that the arguments to static_assert
must be evaluated at compile-time and not at runtime.

What are the arguments to static_assert?

1. 100000<numeric_limits<int>::max() aka
100000 < numeric_limits<int>::max()
2. "small ints!"

The 2nd argument is just the diagnostic message to be printed when the
static assertion fails. The first argument must be something that can
be evaluated at compile-time, so let's look at it more carefully.

It is an application of operator< to 100000 and
numeric_limits<int>::max(). 100000 is a constant, so no problem there.
numeric_limits<int>::max() is an invocation of the max member function
on the class numeric_limits<int>. numeric_limits<int> is known at
compile time, so no problem there. All that's left is the max member
function. This function must be declared constexpr so that it can be
evaluated at compile time, otherwise it would be a compilation error.

template <typename T>
struct foo
{
T max();
};

template<>
struct foo<int>
{
static int max() { return 10; }
};

static_assert(100000 < foo<int>::max(), "whoops");

g++ -c -g -std=c++0x /tmp/a.cpp
/tmp/a.cpp:13:1: error: non-constant condition for static assertion
static_assert(100000 < foo<int>::max(), "whoops");
^
/tmp/a.cpp:13:38: error: call to non-constexpr function 'static int
foo<int>::max()'
static_assert(100000 < foo<int>::max(), "whoops");
^

We can fix this by making the function constexpr, allowing the compiler
to use it at compile time:

template <typename T>
struct foo
{
T max();
};

template<>
struct foo<int>
{
static constexpr int max() { return 10; }
};

static_assert(100000 < foo<int>::max(), "whoops");

g++ -c -g -std=c++0x /tmp/a.cpp
/tmp/a.cpp:13:1: error: static assertion failed: whoops
static_assert(100000 < foo<int>::max(), "whoops");
^
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Richard

unread,
Jun 15, 2015, 2:52:26 PM6/15/15
to
[Please do not mail me a copy of your followup]

Marcel Mueller <news.5...@spamgourmet.org> spake the secret code
<mln3o2$bf8$1...@gwaiyur.mb-net.net> thusly:

>On 15.06.15 19.48, Doug Mika wrote:
>> I will admit, I've tried to understand as precisely as possible what
>constexpr does. I think I have an idea, but I know it's not what it
>should be. So perhaps asking the following will further shed light on
>what constexpr does:
>>
>> static_assert(100000<numeric_limits<int>::max(),"small ints!");
>>
>> and then it says:
>> "Note that the second assert (only) works because
>numeric_limits<int>::max() is a constexpr function"
>>
>> Can someone quickly explain why that is so?
>
>Because the function is not yet compiled it cannot be called.

Wrong.

>Furthermore it might be non deterministic. I.e. it is not clear whether
>the assertion should fail or not. Think about cross compilation.

Also wrong.

Cross-compilation and "not yet compiled" have nothing to do with
constexpr and static_assert.

Doug Mika

unread,
Jun 15, 2015, 5:10:15 PM6/15/15
to
Yes, the problem is with constexpr, in particular, I'm having problems understanding when can I declare a function as constexpr?

So here I came upon a constexpr factorial function:
constexpr int fac(int n) { return (n<2)?1:n*fac(n-1); }

But if constexpr functions must be evaluated at compile-time, then how will the compiler know the size of n at compile time, especially if n is a user-input variable?

Richard

unread,
Jun 15, 2015, 5:30:15 PM6/15/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<2ad4326f-69fb-41b0...@googlegroups.com> thusly:

>Yes, the problem is with constexpr, in particular, I'm having problems
>understanding when can I declare a function as constexpr?

See <http://en.cppreference.com/w/cpp/language/constexpr> for a list of
requirements on constexpr functions.

>So here I came upon a constexpr factorial function:
>constexpr int fac(int n) { return (n<2)?1:n*fac(n-1); }
>
>But if constexpr functions must be evaluated at compile-time, then how
>will the compiler know the size of n at compile time, especially if n is
>a user-input variable?

You can't invoke this function at compile-time without specifying the
value for n as some integral type constant or constant expression.

Doug Mika

unread,
Jun 16, 2015, 11:49:49 AM6/16/15
to
Well, I had a look at the link you provided, I have actually seen it before, but it's not something I understand. Is there any chance that someone could quickly, in laymen terms, explain why the following function can be constexpr if it has a run-time variable as a parameter? And it's even allowed to call itself?

Bo Persson

unread,
Jun 16, 2015, 12:14:22 PM6/16/15
to
On 2015-06-16 17:49, Doug Mika wrote:
> On Monday, June 15, 2015 at 4:30:15 PM UTC-5, Richard wrote:
>> [Please do not mail me a copy of your followup]
>>
>> Doug Mika <doug...@gmail.com> spake the secret code
>> <2ad4326f-69fb-41b0...@googlegroups.com> thusly:
>>
>>> Yes, the problem is with constexpr, in particular, I'm having problems
>>> understanding when can I declare a function as constexpr?
>>
>> See <http://en.cppreference.com/w/cpp/language/constexpr> for a list of
>> requirements on constexpr functions.
>>
>>> So here I came upon a constexpr factorial function:
>>> constexpr int fac(int n) { return (n<2)?1:n*fac(n-1); }
>>>
>>> But if constexpr functions must be evaluated at compile-time, then how
>>> will the compiler know the size of n at compile time, especially if n is
>>> a user-input variable?
>>
>> You can't invoke this function at compile-time without specifying the
>> value for n as some integral type constant or constant expression.
>
> Well, I had a look at the link you provided, I have actually seen it before, but it's not something I understand. Is there any chance that someone could quickly, in laymen terms, explain why the following function can be constexpr if it has a run-time variable as a parameter? And it's even allowed to call itself?
>
> constexpr int fac(int n) { return (n<2)?1:n*fac(n-1); }
>

It is constexpr if the parameter is known at compile time, like if it is
itself constexpr or a literal. In that case the compiler is required to
compute the value during compilation. And the result can be used as a
constant.

This doesn't in any way stop you from ALSO using the same function with
a non-const parameter, but of course then it will be evaluated at runtime.


Bo Persson

Victor Bazarov

unread,
Jun 16, 2015, 12:14:23 PM6/16/15
to
On 6/16/2015 11:49 AM, Doug Mika wrote:
> [...]Is there any chance that someone could quickly, in laymen
> terms,
explain why the following function can be constexpr if it has a run-time
variable as a parameter? And it's even allowed to call itself?
>
> constexpr int fac(int n) { return (n<2)?1:n*fac(n-1); }

Write a small main program:

int main(int argc, char *argv[]) {
constexpr int fac10 = fac(10);
}

Is it OK? Now change the call to 'fac' to use not a constant by some
run-time variable, like 'argc'. Is it still OK?

Declaration of a function as 'constexpr' makes (a) the function itself
inline, and (b) allows the function to be called in an expression that
is expected to be 'const'. If the expression is not 'const', then
'constexpr' is simply ignored, I think. For instance, you can't do

constexpr int fac_argc = fac(argc);
// not allowed - 'argc' is not const

but it's totally OK to do

int fac_argc = fac(argc);

in which case 'constexpr' doesn't matter.

Marcel Mueller

unread,
Jun 16, 2015, 12:29:27 PM6/16/15
to
On 15.06.15 20.52, Richard wrote:
> Cross-compilation and "not yet compiled" have nothing to do with
> constexpr and static_assert.

Well, constexpr forces a function to be deterministic, side effect free
and compile time evaluable. Although the exact definition depends on the
C++ standard version and includes some other constraints to ensure that
it can be evaluated. The newer the standard the more is allowed. From my
point of view this has to do with compilation.

Marcel

Richard

unread,
Jun 16, 2015, 1:38:23 PM6/16/15
to
[Please do not mail me a copy of your followup]

Marcel Mueller <news.5...@spamgourmet.org> spake the secret code
<mlpisu$orb$1...@gwaiyur.mb-net.net> thusly:
Again, this has nothing to do with "not yet compiled" and cross-compilation.

Cross-compilation is compiling source code on one architecture that
targets another architecture other than that which is hosting the
compiler. This has nothing to do with constexpr.

You don't even state precisely what you mean by "not yet compiled", so
there isn't anything more to be said about that. If you mean that a
constexpr function must be *defined* (and not just declared) in order
to be called as part of constructing a larger constant expression,
that is true.

A function can be declared constexpr, but not yet defined in the
current translation unit, and still be used to generate a value at
runtime.
0 new messages