Search code examples
c++android-ndkc++17constexprclang++

Assigning to const char * in constexpr constructor (c++17) fails using Android NDK


I'm trying to use a modified version of the compile-time string classes described in this nice post: https://akrzemi1.wordpress.com/2017/06/28/compile-time-string-concatenation/

The reason for this is that a bunch of string literals need to be adapted based on a compile time constant, so it would make sense to do this adaption at compile time rather than during runtime.

Since I'm able to use c++17 in the project I can make use of the relaxed restrictions for constexpr constructors. Leaving me with the following (simplified) code:

template<int N>
class array_string {
    char _array[N + 2 + 1];
    
public:
    constexpr array_string(const char (&sl)[N + 1]) {
    
        int j = 0;
                
        // here some work based on sl is actually done, but compilation also fails if removed
     
        // overwrite remaining elements with zero bytes.
        for (; j < N + 2 + 1; j++) {
            _array[j] = '\0';
        }
    
    }
    
    constexpr const char *c_str() const { return _array; }
};
    
// C++17 deduction guide:
template<int N_PLUS_1>
array_string(const char (&lit)[N_PLUS_1])   
-> array_string<N_PLUS_1 - 1>;

If I force the creation of a constexpr variable at some other point in the code by writing:

constexpr auto cmpStr = array_string("test");  

Everything compiles as expected using my Linux-Desktop machine using clang 10 and libc++. (I also checked that the modified strings are included in the binary. They are!). The moment I'm trying to compile the same code for android however, I get the following error message:

error: constexpr variable 'cmpStr' must be initialized by a constant expression

The error seems to lay in the assignment to _array inside the constructor body. I'm really confused now, since I thought this would be allowed since c++14. Since other c++14/c++17 features in the project are working (for example the deduction guides) I'm really puzzled why this isn't.

I tried to find information online that this feature is not supported by the ndk, but weren't able to do so. Maybe I'm missing the right keyword to search for.

So far I'm dropping the constexpr constraint on cmpStr to get it compiling for android, which will most likely result in runtime execution of the constructor code, which is a bit unsatisfying.

I'd be happy if someone could point out why this is not working using the android ndk or any other problem. Thanks in advance!

Some details of the building process:

  • ndk version: 21.3.6528147
  • cppFlags "-std=c++1z"
  • arguments "-DANDROID_STL=c++_shared"

Solution

  • Months later I actually noticed that if I explicitly initialize the array_string member, it works on android as well.

    template<int N>
    class array_string {
        char _array[N + 2 + 1]{}; // use default {}-initialization
        
    public:
        // ... see code from question