Mapbox GL Native supports the C++14 standard, and encourages contributions to
the source code using modern C++ idioms like return type deductions, generic
lambdas, std::optional
and alike. However, we do not support all the features
from the final draft of the C++14 standard - we had to sacrifice support for
these features in order to support GCC from version 4.9 onwards.
The following C++14 features are not supported in Mapbox GL Native:
Constructs like the example below are not supported:
template<typename T> constexpr T pi = T(3.14);
- If the variable is an alias, use the call the alias points to: example
// auto foo = pi<double>;
auto foo = double(3.14);
Constructs like the example below are not supported:
struct Foo {
int x = { 0 };
};
// error: no matching function for call to 'Foo::Foo(<brace-enclosed initializer list>)'
int main() {
Foo foo { 0 };
return 0;
}
- Replace data member initializers with default parameter values in default constructors:
struct Foo {
Foo(int x_ = 0) : x(x_) {}
int x;
};
int main() {
Foo foo { 0 }; // works with default constructor
return 0;
}
- Replace bracket initialization with regular round brackets or none:
struct Foo {
Foo(int x_ = 0) : x(x_) {}
int x;
};
int main() {
Foo foo(); // works
Foo bar; // also works
return 0;
}
GCC 4.9 strictly forbids constexpr
usage in the following scenarios:
- No local variable declarations (not
static
orthread_local
, and no uninitialized variables) - Cannot mutate objects whose lifetime began with the constant expression evaluation
- Disable usage of if, switch, for, while, do-while (not goto) inside constexpr expressions
- Enforces that constexpr member functions are implicitly const
// sorry, unimplemented: use of the value of the object being constructed
// in a constant expression
struct Foo {
int x, y;
constexpr Foo(int i) : x(i), y(x) {}
};
// error: body of constexpr function 'constexpr int test1(int)' not a
// return-statement
constexpr int test1(int i) {
int j = i;
return j;
}
// error: body of constexpr function 'constexpr bool test2(int)' not a
// return-statement
constexpr bool test2(int i) {
if (i > 0) {
return true;
} else {
return false;
}
}
- Either remove
constexpr
specifier or replace it withinline
in case of functions
GCC 5.2.0 crashes with polymorphic lambdas and this version of the compiler is currently used in Qt Automotive. Luckily polymorphic lambdas are rarely used/needed but we had one incident fixed by #9665.
- Copy & Paste™ the code.
Compilers with only partial C++11 support causes compilation errors when using-declaration is used in derived class to inherit its base class's constructors (e.g. using Base::Base;)
.
#include <vector>
template <typename T>
struct Varargs : std::vector<T>
{
using std::vector<T>::vector;
};
// error: conflicts with version inherited from 'std::__1::vector<int, std::__1::allocator<int> >'
int main()
{
Varargs<int> v;
return 0;
}
- Replace using-declaration (e.g. using Base::Base;) in derived class with
universal forwarding constructor
.
#include <vector>
template <typename T>
struct Varargs : std::vector<T>
{
template <class... Args>
Varargs(Args&&... args) : std::vector<T>(std::forward<Args>(args)...) {}
};
int main()
{
Varargs<int> v;
return 0;
}
Note: Using universal forwarding constructor
may not be appropriate when derived class has additional members that are not in base class. Write constructors for the derived class explicitly instead of using universal forwarding constructor
when the derived class has additional members.