7
votes

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.

3
Produces "statement not allowed in constexpr function" on clang 3.4.pmr
What version of clang are you using?Stephen Canon
I am using clang 3.5 std=c++1yTory Webster
I didn't even think clang allowed constexpr in generalSyntactic Fructose
@ToryWebster So why are you tagging this c++11? The answer to your question depends on it.pmr

3 Answers

2
votes

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.

10
votes

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.

0
votes

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?