Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Is it possible for C++ code to conform to both the C++03 standard and the C++11 standard, but do different things depending on under which standard it is being compiled?

like image 803
Erik Sjölund Avatar asked Apr 13 '14 19:04

Erik Sjölund


People also ask

Is C++ backwards compatible with C?

C++ is not fully backward compatible with C, wherever it's needed it has drawn a line.

Can we use both C and C++ together?

If the C++ compiler provides its own versions of the C headers, the versions of those headers used by the C compiler must be compatible. Oracle Developer Studio C and C++ compilers use compatible headers, and use the same C runtime library. They are fully compatible.

Are all valid C programs valid C++ programs?

In the strict mathematical sense, C isn't a subset of C++. There are programs that are valid C but not valid C++ and even a few ways of writing code that has a different meaning in C and C++.

How is C++ incompatible with C?

Constructs valid in C but not in C++ C++ enforces stricter typing rules (no implicit violations of the static type system), and initialization requirements (compile-time enforcement that in-scope variables do not have initialization subverted) than C, and so some valid C code is invalid in C++.


1 Answers

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"; } 
like image 58
11 revs, 8 users 80% Avatar answered Oct 13 '22 21:10

11 revs, 8 users 80%