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.
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, or
std::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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With