How Are You Using C++11 Today

How do I check for C++11 support?

Quick history

When this question was asked in February 2011, support for C++11 was inconsistent. Compilers needed time to catch up to the standard, so in the meantime, they released with partial support. For example, a compiler might have implemented variadic templates, but not auto.

If you had code that depended on a subset of C++11 features, you didn't have a standard way of asking the compiler whether it supported them specifically.

You could check for overall C++11 support with #if __cplusplus >= 201103L, but:

  • That constant and its meaning weren't technically official until the standard was accepted later, in August 2011.
  • This was too coarse. Compilers probably only set __cplusplus to 201103L once they had full feature support—and no one had full feature support yet. So, if you used this, you would unnecessarily reject most or all of the compilers that people would want to use to compile your code.

One pragmatic solution was to use the third-party Boost.Config library, which maintained a bunch of feature test macros. Boost.Config's maintainers kept track of which compilers supported which features, and updated the macros accordingly for each Boost.Config release.

(This stuff about Boost is based on an early, now-deleted answer from @James McNellis.

Today

C++11

Today, there's a version of every major compiler that supports the whole C++11 standard. .

If your code requires any of C++11, it's now reasonable to require that the compiler supports all of C++11. So, use #if __cplusplus >= 201103L. (See @Paulo M's answer for a standards reference for this macro.) But beware that there are complications with MSVC—see @Donald Duck's answer.

Beyond

Since C++20, in addition to the coarse-grained __cplusplus macro, you can also #include <version> to get a bunch of feature test macros. This is basically a standards-based alternative to Boost.Config.

According to this answer from Jarryd, these macros are actually available in at least some 2016-era C++14 compilers.

C++11: a new language?

In short, no, we can't consider this a new language. It's the same language, new features. But instead of being bolted on by using the Boost libs, they're now going to be standard inclusions if you're using a compiler that supports the 0x standard.

One doesn't have to use the new standard while using a compiler that supports the new standard. One will have to learn and use the new standard if certain constraints exist on the software being developed, however, but that's a constraint with any software endeavor. I think that the new features that the 0x standard brings will make doing certain things easier and less error prone, so it's to one's advantage to learn what the new features are, and how they will improve their design strategy for future work. One will also have to learn it so that when working on software developed with it, they will understand what's going on and not make large boo-boos.

As to whether I will "switch to the new standard", if that means that I will learn the new standard and use it where applicable and where it increases my productivity, then yes, I certainly plan to switch. However, if this means that I will limit myself to only working with the new features of the 0x standard, then no, since much of my work involves code written before the standard and it would be a colossal undertaking to redesign everything to use the new features. Not only that, but it may introduce new bugs and performance issues that I'm not aware of without experience.

Learning C++ has always been one of the more challenging journeys a programmer can undertake. Adding new features to the language will not change the difficulty of learning its syntax and how to use it effectively, but the approach will change. People will still learn about pointers and how they work, but they'll also learn about smart pointers and how they're managed. In some cases, people will learn things differently than before. For example, people will still need to learn how to initialize things, but now they'll learn about Uniform Initialization and Initializer Lists as primary ways to do things. In some cases, perhaps understanding things will be easier with the addition of the new for syntax for ranges or the auto return type in a function declaration. I think that overall, C++ will become easier to learn and use while at the same time becoming easier to teach.

Mastering a language is a long-term goal, it can not be done over night. It's silly to think that one can have mastery over something as complex as C++ quickly. It takes practice, experience and debugging code to really hammer something in. Academically learning is one thing, but putting to use that knowledge is an entire different monster. I think that if one already has mastery of the C++ language, the new concepts will not pose too much of a burden, but a new comer may have an advantage in that they won't bother learning some of the more obsolete ways of doing things.

C++11 Compiler: Closest to the standard and how close?

There's a support matrix on the Apache wiki.

Compiling C++11 with g++

Flags (or compiler options) are nothing but ordinary command line arguments passed to the compiler executable.

Assuming you are invoking g++ from the command line (terminal):

$ g++ -std=c++11 your_file.cpp -o your_program

or

$ g++ -std=c++0x your_file.cpp -o your_program

if the above doesn't work.

How do I enable C++11 in gcc?

H2CO3 is right, you can use a makefile with the CXXFLAGS set with -std=c++11
A makefile is a simple text file with instructions about how to compile your program. Create a new file named Makefile (with a capital M). To automatically compile your code just type the make command in a terminal. You may have to install make.

Here's a simple one :

CXX=clang++
CXXFLAGS=-g -std=c++11 -Wall -pedantic
BIN=prog

SRC=$(wildcard *.cpp)
OBJ=$(SRC:%.cpp=%.o)

all: $(OBJ)
$(CXX) -o $(BIN) $^

%.o: %.c
$(CXX) $@ -c $<

clean:
rm -f *.o
rm $(BIN)

It assumes that all the .cpp files are in the same directory as the makefile. But you can easily tweak your makefile to support a src, include and build directories.

Edit : I modified the default c++ compiler, my version of g++ isn't up-to-date. With clang++ this makefile works fine.

How to Program C++11 Using Qt5?

QMAKE_CXXFLAGS += -std=c++0x

Results in an error because you're not using the MinGW compiler. "D9002: Ignoring unknown option -std=c++0x" is an error from the MSVC compiler.

In QtCreator, go to the projects tab(on the left) and change the toolchain you're using. If it hasn't auto-detected MinGW, you're going to have to add it yourself by clicking on the manage button.

Can C++ code be valid in both C++03 and C++11 but do different things?

The answer is a definite yes. On the plus side there is:

  • Code that previously implicitly copied objects will now implicitly move them when possible.

On the negative side, several examples are listed in the appendix C of the standard. Even though there are many more negative ones than positive, each one of them is much less likely to occur.

String literals

#define u8 "abc"
const char* s = u8"def"; // Previously "abcdef", now "def"

and

#define _x "there"
"hello "_x // Previously "hello there", now a user defined string literal

Type conversions of 0

In C++11, only literals are integer null pointer constants:

void f(void *); // #1
void f(...); // #2
template<int N> void g() {
f(0*N); // Calls #2; used to call #1
}

Rounded results after integer division and modulo

In C++03 the compiler was allowed to either round towards 0 or towards negative infinity. In C++11 it is mandatory to round towards 0

int i = (-1) / 2; // Might have been -1 in C++03, is now ensured to be 0

Whitespaces between nested template closing braces >> vs > >

Inside a specialization or instantiation the >> might instead be interpreted as a right-shift in C++03. This is more likely to break existing code though: (from http://gustedt.wordpress.com/2013/12/15/a-disimprovement-observed-from-the-outside-right-angle-brackets/)

template< unsigned len > unsigned int fun(unsigned int x);
typedef unsigned int (*fun_t)(unsigned int);
template< fun_t f > unsigned int fon(unsigned int x);

void total(void) {
// fon<fun<9> >(1) >> 2 in both standards
unsigned int A = fon< fun< 9 > >(1) >>(2);
// fon<fun<4> >(2) in C++03
// Compile time error in C++11
unsigned int B = fon< fun< 9 >>(1) > >(2);
}

Operator new may now throw other exceptions than std::bad_alloc

struct foo { void *operator new(size_t x){ throw std::exception(); } }
try {
foo *f = new foo();
} catch (std::bad_alloc &) {
// c++03 code
} catch (std::exception &) {
// c++11 code
}

User-declared destructors have an implicit exception specification
example from What breaking changes are introduced in C++11?

struct A {
~A() { throw "foo"; } // Calls std::terminate in C++11
};
//...
try {
A a;
} catch(...) {
// C++03 will catch the exception
}

size() of containers is now required to run in O(1)

std::list<double> list;
// ...
size_t s = list.size(); // Might be an O(n) operation in C++03

std::ios_base::failure does not derive directly from std::exception anymore

While the direct base-class is new, std::runtime_error is not. Thus:

try {
std::cin >> variable; // exceptions enabled, and error here
} catch(std::runtime_error &) {
std::cerr << "C++11\n";
} catch(std::ios_base::failure &) {
std::cerr << "Pre-C++11\n";
}

Should I use C++11 lambdas now?

Do you need to be able to compile your code using a compiler that doesn't support C++11 lambdas?

If so, then you can't use them (obviously). Otherwise, there's really not much reason not to use them.

There have been few changes to the specification of lambda expressions in C++11, so there is little risk to using them now. Certainly there will be occasional compiler bugs, but for the most part those are few and far between.

The only major lambda-related feature of which I am aware that is not supported by the latest versions of multiple compilers that support lambda expressions is one that was added last March, which allows captureless lambdas to be implicitly converted to function pointers. Visual C++ 2010 and Intel C++ 11.1 don't support that (I don't have a later version of Intel C++ with which to test, sorry). Visual C++ 11 does support the implicit conversion, however.



Related Topics



Leave a reply



Submit