8

Let's take this simple example:

#include <iostream>

namespace foo {
    constexpr int main(int argc, char* argv[]) {
      // code
    }
}

int main(int argc, char* argv[])
{
    return foo::main(argc, argv);
}

Depend on what code is, clang will complain or no. If code is:

cout << "Hello!";
return 0;

clang complains:

error: constexpr function never produces a constant expression [-Winvalid-constexpr]

constexpr int main(int argc, char* argv[]) {

note: non-constexpr function 'operator<< >' cannot be used in a constant expression

    std::cout << "Hello!";

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5: note: declared here

operator<<(basic_ostream<char, _Traits>& __out, const char* __s)

Fair enough, constexpr functions can't contain any cout statements, as we know. But what happens if we do this?

  for (int i = 0; i < argc; i++)
    std::cout << argv[i];

clang allows it! OK, but this can't possibly be a constexpr function even though it is marked constexpr, let's try to use it in constexpr context.

int arr[foo::main(argc, argv)];

It works! So it must be clang bug? Reason I say clang because gcc complains:

error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement

So my conclusion is clang is wrong and gcc is right.

6
  • 2
    Produces "statement not allowed in constexpr function" on clang 3.4. Commented Feb 3, 2014 at 23:50
  • What version of clang are you using? Commented Feb 3, 2014 at 23:51
  • I am using clang 3.5 std=c++1y Commented Feb 3, 2014 at 23:51
  • I didn't even think clang allowed constexpr in general Commented Feb 3, 2014 at 23:56
  • 3
    @ToryWebster So why are you tagging this c++11? The answer to your question depends on it. Commented Feb 3, 2014 at 23:56

3 Answers 3

13

Clang is correct here.

First example

Here, the code is:

constexpr int foo::main(int argc, char* argv[]) {
  std::cout << argv[i];
  return 0;
}

In C++11, this code is ill-formed, because the body contains an expression-statement, which is not permitted in a constexpr function definition.

In C++1y, this code is ill-formed with no diagnostic required, because a call to foo::main can never produce a constant expression (because it always calls operator<<(std::ostream&, const char*), which is not constexpr).

Second example

In this case, the code is:

constexpr int foo::main(int argc, char* argv[]) {
  for (int i = 0; i < argc; i++)
    std::cout << argv[i];
  return 0;
}

In C++11, this code is ill-formed, because it contains a for-statement.

In C++1y, this code is valid. In particular, foo::main(0, 0) is a constant expression (with value 0). Since foo::main is usable in a constant expression, Clang is not permitted to reject it, and does not do so.

Third example

int arr[foo::main(argc, argv)];

The array bound here is not a constant expression (because it reads argc and argv, which are not constant). However, Clang supports variable-length arrays as an extension by default. You can specify -pedantic-errors to put clang into strictly-conforming mode, and in that mode it will reject this code.

GCC's diagnostic:

error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement

is incorrect in both C++11 and C++1y. In C++11, it's incorrect because the rule is more subtle (the body of a constexpr function can contain typedefs and a few other constructs, not just return-statements). In C++1y, the rule no longer exists at all.

Sign up to request clarification or add additional context in comments.

Comments

2

You compile your code in C++1y mode which contains wording to relax constexpr restrictions including all looping statements.

Have a look at N3652 which introduced these changes.

2 Comments

Where is the specific place that allows it to use operator<< on cout?
@Griwes I ignored the body of the for-loop, because I thought that OP is specifically wondering about the loop. But yes, that is odd.
0

So gcc 4.8.1 does not implement relaxed constexpr restraints, but clang 3.5 does. My mistake was that clang and gcc both have variable length array extensions. if I had used std::array instead, both compilers would reject the code. What I still don't understand is if clang allows relaxed constexpr, then why is it not a constexpr?

2 Comments

Because operator<< is not constexpr.
I suggest compiling with at least -pedantic to avoid this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.