Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument only used in unevaluated context within the body of a constexpr function

The following piece of code has successfully compiled with gcc 5.3.0 but has failed to compile with clang 3.7.0. I used the online coliru compilers with the same command line options in both cases: -std=c++14 -O2 -Wall -pedantic -pthread.

#include <cstdio>

// Definition of constexpr function 'foo'.
constexpr std::size_t foo(const int& arg_foo) { return sizeof(arg_foo); }

// Definition of function 'test'.
void test(const int& arg)
{ 
  // The following line produces an error with clang.
  constexpr std::size_t res_foo = foo(arg);

  // Print the result returned by the 'foo' function.
  std::printf("res_foo = %lu\n", res_foo);
}

// Definition of function 'main'.
int main(int argc, const char* argv[])
{
  // Test function call.
  test(argc);

  // Return statement.
  return 0;
}

clang rejects it with the following error:

error: constexpr variable 'res_foo' must be initialized by a constant expression
constexpr size_t res_foo = foo(arg);
                           ~~~~^~~~

Because of this difference between the two compilers, I am wondering if this is a valid piece of code. If not, I would like to get a better understanding of why this is the case.

like image 267
Albert Avatar asked Nov 08 '22 21:11

Albert


1 Answers

You are mixing const and constexpr values together. The definition of constexpr is a value known at compile time. But the argcvariable is only known at run time (it is a number of arguments passed to your executable). So you cannot assign it to another constexpr variable - res_foo. It is Removing constexpr from the res_foo definition will make your code compilable.

The difference between const and constexpr can be simplified to something like this:
const - I'm not going to change this value
constexpr - This value is known at compile time and I'm not going to change it

My guess is that GCC is able to compile this code with O2 since you are not using the arg_foo argument and the size of it is known at the compile time. But it is still syntactically incorrect - compiler should emit an error, since non-constexpr value is assigned to a constexpr variable.

like image 169
DennisS Avatar answered Nov 14 '22 22:11

DennisS