Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare constexpr extern?

Is it possible to declare a variable extern constexpr and define it in another file?

I tried it but the compiler gives error:

Declaration of constexpr variable 'i' is not a definition

in .h:

extern constexpr int i; 

in .cpp:

constexpr int i = 10;  
like image 448
coldbrew Avatar asked May 13 '15 07:05

coldbrew


People also ask

Can constexpr be extern?

Actually, extern constexpr does make sense, and would be useful. In particular, static constexpr class member variables automatically have external linkage (which is a huge inconsistency and gotcha - people often forget to add a definition in a . cc file).

Where do I put constexpr?

In other words, you should use constexpr for your constants in header files, if possible, otherwise const . And if you require the address of that constant to be the same everywhere mark it as inline .

Can constexpr throw exception?

Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.

What is constexpr keyword in C++?

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value. Unlike const , constexpr can also be applied to functions and class constructors.


2 Answers

no you can't do it, here's what the standard says (section 7.1.5):

1 The constexpr specifier shall be applied only to the definition of a variable or variable template, the declaration of a function or function template, or the declaration of a static data member of a literal type (3.9). If any declaration of a function, function template, or variable template has a constexpr specifier, then all its declarations shall contain the constexpr specifier. [Note: An explicit specialization can differ from the template declaration with respect to the constexpr specifier. Function parameters cannot be declared constexpr. — end note ]

some examples given by the standard:

  constexpr void square(int &x);  // OK: declaration   constexpr int bufsz = 1024;  // OK: definition   constexpr struct pixel {  // error: pixel is a type     int x;     int y;     constexpr pixel(int);  // OK: declaration   };    extern constexpr int memsz; // error: not a definition 
like image 193
swang Avatar answered Sep 19 '22 16:09

swang


C++17 inline variables

This awesome C++17 feature allow us to:

  • conveniently use just a single memory address for each constant
  • store it as a constexpr
  • do it in a single line from one header

main.cpp

#include <cassert>  #include "notmain.hpp"  int main() {     // Both files see the same memory address.     assert(&notmain_i == notmain_func());     assert(notmain_i == 42); } 

notmain.hpp

#ifndef NOTMAIN_HPP #define NOTMAIN_HPP  inline constexpr int notmain_i = 42;  const int* notmain_func();  #endif 

notmain.cpp

#include "notmain.hpp"  const int* notmain_func() {     return &notmain_i; } 

Compile and run:

g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o ./main 

GitHub upstream.

The C++ standard guarantees that the addresses will be the same. C++17 N4659 standard draft 10.1.6 "The inline specifier":

6 An inline function or variable with external linkage shall have the same address in all translation units.

cppreference https://en.cppreference.com/w/cpp/language/inline explains that if static is not given, then it has external linkage.

See also: How do inline variables work?

Tested in GCC 7.4.0, Ubuntu 18.04.