Question

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.

Was it helpful?

Solution 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.

OTHER TIPS

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.

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top