Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use C++14 in a library meant for C++11 client applications?

Tags:

c++

c++11

c++14

If I'm building a library where I assume that some "clients" of the library may only be using C++11, can I compile the library itself using C++14 for its internals? Are there API/ABI/link compatibility issues versus C++11? Is it safe to implement and build the library with C++14 as long as I avoid certain new features in the public API, and if so, what must I avoid? Or is it inherently incompatible to mix C++11 and C++14 within the final software project?

It's a cross-platform library, BTW, so I'll need to build it on Linux, OSX, and Windows.

like image 760
Larry Gritz Avatar asked Sep 25 '15 17:09

Larry Gritz


1 Answers

If I'm building a library where I assume that some "clients" of the library may only be using C++11, can I compile the library itself using C++14 for its internals?

Yes, in general that should be possible.

I do exactly that for GCC's implementation of the Filesystem TS. The <experimental/filesystem> header is written in pure C++11 and can be included by C++11 clients, but the implementation in libstdc++fs.a is written in C++14.

Are there API/ABI/link compatibility issues versus C++11?

There are no changes between C++11 and C++14 that require implementations to break their link-time compatibility. That doesn't mean implementations won't break it, but they aren't required to.

For GCC I believe C++11 and C++14 are entirely API and ABI compatible, except for the constexpr and sized-deallocation issues mentioned below.

Is it safe to implement and build the library with C++14 as long as I avoid certain new features in the public API, and if so, what must I avoid?

It depends on your compiler, but in theory it's possible.

Obviously avoid any C++14 language features that aren't valid in C++11 (such as function return type deduction, or generic lambdas with auto parameters, or variable templates) and any C++14 library entities, like std::make_unique, std::integer_sequence, orstd::shared_timed_mutex`.

A list of nearly all the changes in C++14 can be found in SD-6.

One thing to watch out for is that the meaning of a non-static constexpr member function changed between C++11 and C++14. In C++11 this member function is const:

struct X {
  constexpr int foo();
};

In C++14 it is non-const. To be compatible with both C++11 and C++14 you should explicitly qualify it as const:

struct X {
  constexpr int foo() const;
};

That means the same thing in both C++11 and C++14.

Another caveat is that in C++11 and C++14 this operator means something different:

void operator delete(void*, std::size_t);

If C++11 client code defines that function then your library compiled in C++14 could end up calling it instead of the usual operator delete(void*) and that would presumably do the wrong thing. This is probably very uncommon and not a problem in real code, but it's possible. G++ and Clang allow you to compile C++14 code with -fno-sized-deallocation to disable the new feature, so that your C++14 library code would never call that version of operator delete.

like image 119
Jonathan Wakely Avatar answered Nov 12 '22 08:11

Jonathan Wakely