In C++20 u8 string literals are based on the char8_t type. They deliberately do not convert to char const* any more:
const char* str = u8"Hall\u00f6chen \u2603"; // no longer valid in C++20
Of course, the ultimate goal when migrating to C++20 is to entirely go with the new behaviour (in the example above: change the type of str). However, because of 3rd party libraries, this is often not possible immediately.
The proposals that introduce and "remedy" char8_t anticipate that and mention that in clang and gcc there is the -fno-char8_t flag to switch back to the old behaviour (while still being able to enjoy other C++20 features).
The 2nd proposal sets up the expectation that Microsoft will follow and add a similar flag, but I was not able to find how to set it (at least in VS 2019, Version 16.4).
So does anyone know what the MSVC equivalent for -fno-char8_t is?
Since 16.1, there is the conformance compiler flag /Zc:char8_t-. The minus tells the compiler to not use conformance mode here when using C++20. On the contrary, /Zc:char8_t can be used to enable it.
Related
I'm starting to add [[nodiscard]], [[noreturn]] and [[fallthrough]] to my code base, but I still worry the code might need to be used on an older C++ version.
I'm only worried about g++, clang, and Visual Studio.
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
Were these allowed and ignored (or supported) even before C++11? (I ask not what the spec says but what the software actually did.)
#if __cplusplus >= 201703L
#define MyNamespace_NoReturnCPP17 [[noreturn]]
#else
#define MyNamespace_NoReturnCPP17
#endif
(Off subject but if I were on the C++ committee, I'd re-use the case keyword to do the same thing as switch, when followed by (, except it would in effect have an automatic break before each case label. And within the case's block (and nowhere else), fallthrough would be accepted as a keyword, that suppresses that automatic break.)
I note the C++14 spec 7.6.1.5 says behavior is "implemenation-defined" but I'm asking a more practical question about what compilers actually did. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
The C++17 spec 10.6.1.6 says "Any attribute-token that is not recognized by the implementation is ignored." That answers my question for C++17 and newer, but again my question is about earlier compilers. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf
To be safe should I make every single usage depend on a version check for the exact version it appeared? Or, do these compilers accept (or does the spec even mandate they accept) any [[attribute]] even if unknown, starting with C++11?
I prefer adding version checks for safety although mainstream compilers will throw a warning for unknown attributes.
gcc -Wno-ignored-attributes / -Wattributes
Clang -Wunknown-attributes
MSVC C5030
I'm not sure these warning options(and corresponding behavior) have been added since the first C++11 feature-complete version, so you'd better do some checks.
Were these allowed and ignored (or supported) even before C++11?
Since standard attributes syntax is supported starting from C++11, compilers will have trouble at the parsing stage. Demo
C++11 allows initializing a value with zero using the expression T(); (http://en.cppreference.com/w/cpp/language/zero_initialization). Is this feature supported by Visual Studio 2010? I ran some experiments comparing T x; with T x = T(); and I concluded that the latter case does initialize the value with zero, but I am not sure whether I can rely on that.
Is zero initialization mentioned anywhere in the VS2010 documentation? The VS2010 Initializers page (https://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.100).aspx) does not mention it, unlike pages for later versions, e.g., VS2013 (https://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.120).aspx).
This is a fundamental behaviour of the language that has been in there since the start. It was not introduced in C++11 (on that cppreference page note that "since C++11" is aligned with only the third of the examples under usage (2); granted it's not very clear).
If T were int and T() did not result in a temporary int of value zero (and this is zero-initialisation via value-initialisation), the compiler would have a very serious bug. I am sure that Visual Studio does not have this bug.
As for proof, the VS2010 docs do not seem to mention this behaviour in the same place the standard mentions it (i.e. under the explicit type conversion expression section). It is certainly possible that their documentation has changed/evolved/become more thorough over time, though, particularly as C++ itself added more and more ways to initialise things.
I see Q_NULLPTR being used liberally in Qt source code and examples, but I have found no documentation for what it is exactly and when it should be used.
For example in this official demonstration of the new Qt SerialBus module added in the new Qt v5.6:
if (!m_canDevice->connectDevice()) {
delete m_canDevice;
m_canDevice = Q_NULLPTR;
Did this serve the purpose of nullptr prior to that being added in C++11? If so, now that we have C++11, should I be using Q_NULLPTR?
PS: I tried searching the Qt source code for the definition of the macro but failed to find it.
Q_NULLPTR is a macro, that is replaced as nullptr if compiler supports c++11 and as NULL (which is replaced as 0) if it doesn't. If you use c++11, you can write nullptr instead; use NULL if you don't.
Did this serve the purpose of nullptr prior to that being added in
C++11? If so, now that we have C++11, should I be using Q_NULLPTR?
Yes (somewhat) and No respectively.
C++ was quite lacking back in the days, so Qt had its own stuff, which later became obsolete as C++ caught up on the features.
That being said, Q_NULLPTR is (was) not functionally the same as nullptr, (as Andrei noted, if C++11 is supported it expands to nullptr) it didn't give you the type safety, just syntax "sugar". It illustrated the intent to the person reading the code, not to the compiler as nullptr does.
Actually Q_NULLPTR had only one purpose: To allow use of nullptr without loosing support for compilers which didn't have C++11/C++0x support, as a direct use of nullptr would result in errors in such setups. The downside is that there are ambiguities of its fallback to NULL (or 0 in older Qt versions) which might result in unintended runtime behavior and limit the supported use cases compared to nullptr.
In the rare case that you target non C++11 compliant compilers, use Q_NULLPTR but make sure that the code works well when C++11 features are disabled. In all other situations nullptr is the better alternative as it results in compilation errors instead of buggy runtime behavior when used with legacy compilers. Qt 5.7 and later dropped the support for compilation without C++11 so there is no need for Q_NULLPTR if you depend on those versions.
There are other features like qMove or Q_DECL_OVERRIDE that give improved semantic when used on supporting compilers without breaking compilation on older compilers.
Use Q_NULLPTR to stay compiler independent.
If you now decide to use nullptr, your code won't compile with an older c++98 compiler. If you decide to use NULL, you lose the c++11 type safety, even if available in your current compiler.
For the same reason macros like qMove(x) and the corresponding define Q_COMPILER_RVALUE_REFS exists.
Consider this program:
#include <iostream>
int main()
{
delete std::cout;
}
AFAIK the conversion function operator void* () const has been removed from C++11. So, this program should fail in compilation on a C++11 compiler. Ya, its true that both g++ 4.8.1 & 4.9.2 gives diagnosis (in the form of warning that deleting void* is undefined & that's also the good thing). But shouldn't this program fail in compilation because removal of that conversion function due to which all stream object could be implicitly converted to void* in C++98 & C++03?. Is this bug? It seems bit surprising that they still not have implemented this change.
I've tried this program in g++ 4.9.2(that supports C++14) but it gives warning not compiler error. Ideone compiler gives me an error as expected. (See live demo here)
It has nothing to do with the compiler, its a library issue. libstdc++ has lots of incompatibilities with C++11, of which this is just one. They are making breaking changes in 5 and up though iirc.
In short, it's neither a bug nor a compiler issue.
This is a bug in the standard library (if you view it as an implementation of the C++11/14 standard library rather than C++98/03).
It's sort of a compiler issue as well though. Specifically, removing the conversion to void * depends on adding a conversion directly to bool--but that, in turn, depends on adding "contextual conversion" to the compiler.
gcc 4.8 did implement a form of contextual conversion, but not the form that was accepted into the standard. Although the specific changes to contextual conversion wouldn't directly impact this use of contextual conversion, it does point to the fact that the definition of contextual conversion was still being tweaked as these compilers were being written.
The sequence in which things (at least normally) happen is that first the specification is solidified. Then the compiler implements it. Then the standard library puts it to use.
In this case the specification was still changing fairly shortly before the compiler was released. Therefore, the standard library didn't (and practically speaking, couldn't) use it.
By the time of 4.9, the specification was solid, and the compiler implemented the final version of contextual conversion, but it hadn't been around long enough to be put to use in the standard library yet.
The canonical way to read lines from a text file is:
std::fstream fs("/tmp/myfile.txt");
std::string line;
while (std::getline(line, fs)) {
doThingsWith(line);
}
(no, it is not while (!fs.eof()) { getline(line, fs); doThingsWith(line); }!)
This works beacuse std::getline returns the stream argument by reference, and because:
in C++03, streams convert to void*, via an operator void*() const in std::basic_ios, evaluating to the null pointer value when the fail error flag is set;
see [C++03: 27.4.4] & [C++03: 27.4.4.3/1]
in C++11, streams convert to bool, via an explicit operator bool() const in std::basic_ios, evaluating to false when the fail error flag is set
see [C++11: 27.5.5.1] & [C++11: 27.5.5.4/1]
In C++03 this mechanism means the following is possible:
std::cout << std::cout;
It correctly results in some arbitrary pointer value being output to the standard out stream.
However, despite operator void*() const having been removed in C++11, this also compiles and runs for me in GCC 4.7.0 in C++11 mode.
How is this still possible in C++11? Is there some other mechanism at work that I'm unaware of? Or is it simply an implementation "oddity"?
I'm reasonably certain this is not allowed/can't happen in a conforming implementation of C++11.
The problem, of course, is that right now, most implementations are working on conforming, but aren't there completely yet. At a guess, for many vendors, this particular update is a fairly low priority. It improves error checking, but does little (or nothing) to enable new techniques, add new features, improve run-time efficiency, etc. This lets the compiler catch the error you've cited (some_stream << some_other_stream) but doesn't really make a whole lot of difference otherwise.
If I were in charge of updating a standard library for C++11, I think this would be a fairly low priority. There are other changes that are probably as easy (if not easier) to incorporate, and likely to make a much bigger difference to most programmers.
To use one of the examples you gave, if I were in charge of updating the VC++ standard library to take advantage of the compiler features added in the November CTP, my top priority would probably be to add constructors to the standard container types to accept initialization_lists. These are fairly easy to add (I'd guess one person could probably add and test them in under a week) and make quite an obvious, visible difference in what a programmer can do.
As late as GCC 4.6.2, the libstdc++ code for basic_ios is evidently still C++03-like.
I'd simply put this down to "they haven't gotten around to it yet".
By contrast, the libc++ (LLVM's stdlib implementation) trunk already uses operator bool().
This was a missed mini-feature buried in a pre-existing header. There are probably lots of missing error of omission and commission in pre-2011 components.
Really, if anyone comes up with things like this in gcc then it would do a world of good to go to Bugzilla and make a bug report. It may be a low priority bug but if you start a paper trail
I'll go out on a limb and extend this idea to all the other C++ compilers: clang, Visual Studio,etc.
This will make C++ a better place.
P.S. I entered a bug in Bugzilla.