I'm writing a function as part of an experiment with Boost.Interprocess. In the function I assign a string literal to a variable declared constexpr char*. When I do this, I get:
warning: deprecated conversion from string constant to char* [-Wwrite-strings].
My understanding of constexpr is that in a variable declaration it behaves as if the variable was declared const, but with the added stipulation that the variable must be initialized, and that initialization must be with a constant expression.
With this understanding I would expect constexpr char* to behave as const char*, and therefore not issue the warning. Am I missing something about how constexpr works?
I'm compiling with GCC 4.6.0 20110306 using -std=c++0x.
Any reasoning for the warning being issued would be appreciated. Thanks!
The const from constexpr would make your variable char* const.
You still have the problem that the string literal is const char and that converting its address to char* is allowed, but deprecated.
For another solution to this:
Instead of-
constexpr char* foo = "bar";
You can do-
constexpr char foo[] = "bar";
This will also get rid of the warning.
Related
As the keyword constexpr implies const and it can also be calculated at compile time, does it mean that now declaring variables as const doesn't make sense and we should always declare them as constexpr?
and it can also be calculated at compile time, does it mean that now declaring variables as const doesn't make sense and we should always declare them as constexpr?
And must be calculated at compile time (ignoring the as-if rule).
So you can't declare constexpr a variable initialized with a run-time known value. But you can declare it const.
For example: you can't declare bar constexpr
int foo;
std::cin >> foo;
constexpr int bar = foo; // compilation error
but you can declare it const
int foo;
std::cin >> foo;
const int bar = foo; // compile
No, not at all.
constexpr means "constant expression", as in [possibly] statically-known, as in "[possibly] known at compile time".
const means "cannot be changed after initialisation".
These are completely separate concepts. A const object can be initialised with a runtime value, for example.
constexpr can imply const, but const certainly does not imply constexpr.
(I think constexpr is a very confusing name, due to this.)
Adding to #max66 answer: constexpr can only replace a top-level const. It can never replace pointer-to-const or const reference. So, sometimes constexpr and const can be used in the same declaration. E.g.
const char* const s = "Hello";
can be replaced with:
constexpr const char* s = "Hello";
I'm working with with MS Visual Studio 2017, V. 15.9.8.
I am using the excellent JetBrains ReSharper Ultimate 2019.1.2 Build 191.0.20190603.142841. It gives me a warning at the indicated location:
#include <vector>
struct T
{
std::vector<char> m;
const char *f() const
{
static const char emptyData; // ReSharper complains here
return m.size() ? &m[0] : &emptyData;
}
};
The message is
file.h: Static local variable of type 'const unsigned char' should be initialized. This is non-standard Microsoft C++ extension.
The warning disappears if emptyData is not const.
The warning is wrong since all static data, including constant static locals, are per the standard zero-initialized, right?
The warning is wrong since all static data, including constant static locals, are per the standard zero-initialized, right?
It's just slightly inaccurate. There is initial zero initialisation indeed, but after that the variable is default initialised. For char, default initialisation is no initialisation which in case of previous zero initialisation would leave the zero value intact. A pedantically correct message would be that constant objects (of this type) must not be default initialised.
The standard (latest draft says):
If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.
The program violates this rule and is ill-formed.
Note that until C++17 default initialisation was not allowed for any const qualified type.
I believe it's because of the const, constants variables must be initilized, if the line is const char emptyData;, you get an error for uninitialized constvariable, so I think it's not the static modifier that is causing the problem.
There is a topic about this matter that seems interesting here.
Whether it is const static char emptyData; or static const char emptyData; the error in g++2a(GNU) compiler is:
error: uninitialized 'const emptyData' [-fpermissive]
The following program is failing when compiling with Clang with error: constexpr variable 'struct2Var' must be initialized by a constant expression {var, 2100433}
.
If I remove __attribute__((weak)) from "var" declaration, it is passing without any issues.
Can somebody please explain the theory/reason behind this error.
struct myStruct
{
public:
constexpr operator const wchar_t*() const
{
return &m_cch;
}
const wchar_t m_cch;
};
extern __attribute__((weak)) const constexpr myStruct var {'a'};
struct myStruct2
{
const wchar_t* stzKey = nullptr;
int intvar = 0;
};
static constexpr const myStruct2 struct2Var[1]
{
{var, 2100433}
};
It looks like using __attribute__((weak)) discards the constexpr qualifier with clang but not with gcc. Despite clang trying to be a drop in replacement for gcc, it might implement such non standard feature differently. In that case, I would say that neither gcc nor clang is wrong.
Also, global constexpr might be tricky to maintain as they should all be defined consistently in every translation unit. To face this issue, inline variable have been added to c++17.
I came across the following situation:
struct Foo
{
static constexpr char s[] = "Hello world";
};
const char Foo::s[];
This code snippet compiles with Clang 3.7 (with -std=c++11 and -std=c++14), but GCC (4.8, 6.0, same language settings) gives the error I would have expected:
GCC 4.8:
in.cpp:6:19: error: redeclaration ‘Foo::s’ differs in ‘constexpr’
const char Foo::s[];
^
in.cpp:3:27: error: from previous declaration ‘Foo::s’
static constexpr char s[] = "Hello world";
^
in.cpp:6:19: error: declaration of ‘constexpr const char Foo::s [12]’ outside of class is not definition [-fpermissive]
const char Foo::s[];
GCC 6.0:
‘constexpr’ needed for in-class initialization of static data member ‘const char Foo::s [12]’ of non-integral type [-fpermissive]
I found this old question that seems to discuss mixing constexpr and const, but it focusses on whether initializers are constant expressions, rather on whether definition and declaration can differ with regard to constness.
Is it allowed to provide the definition for a constexpr T static data member as a const T?
Your code is well-formed. The constexpr-specifier is not itself part of the type but adds const ([dcl.constexpr]/9), which is present in your second declaration. Although different declarations of one function (or function template) have to agree in constexpr-ness as per [dcl.constexpr]/1, no such rule exists for variable declarations.
See bug #58541, which basically uses your example.
I'm using codepad.org
class a {
private:
const unsigned long b = 100;
};
Line 3: error: ISO C++ forbids initialization of member 'b'
compilation terminated due to -Wfatal-errors.
Sorry if I've missed something obvious, but what could be wrong?
Before C++11, you can only initialise a static const data member in the class definition:
static const unsigned long b = 100;
This is usually what you want anyway. It doesn't make much sense to have all instances of a have this constant value duplicated among them.
If you enable C++11 support, your code will compile.
In-class initialization is only allowed for static const integral types in C++03, and your variable isn't static.
Either make it static (in this case, you should - note that you also have to define it in this casee), or use a C++11 compiler.