Skip to content

Latest commit

 

History

History
168 lines (126 loc) · 4.77 KB

DEVELOPING.md

File metadata and controls

168 lines (126 loc) · 4.77 KB

Modern C++ support

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);

Workarounds:

  • 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;
}

Workarounds

  • 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 or thread_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;
    }
}

Workarounds

  • Either remove constexpr specifier or replace it with inline 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.

Workarounds

  • 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;
}

Workarounds

  • 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.