48

I'm using android NDK r9d and toolchain 4.8 but I'm not able to use std::to_string function, compiler throws this error:

 error: 'to_string' is not a member of 'std'

Is this function not supported on android ndk? I try APP_CPPFLAGS := -std=c++11 with no luck.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
albciff
  • 18,112
  • 4
  • 64
  • 89

6 Answers6

62

You can try LOCAL_CFLAGS := -std=c++11, but note that not all C++11 APIs are available with the NDK's gnustl. Full C++14 support is available with libc++ (APP_STL := c++_shared).

The alternative is to implement it yourself.

#include <string>
#include <sstream>

template <typename T>
std::string to_string(T value)
{
    std::ostringstream os ;
    os << value ;
    return os.str() ;
}

int main()
{
    std::string perfect = to_string(5) ;
}
Dan Albert
  • 10,079
  • 2
  • 36
  • 79
yushulx
  • 11,695
  • 8
  • 37
  • 64
  • 3
    I make some tries with no luck (LOCAL_CPPFLAGS += -std=c++11, LOCAL_CPPFLAGS += -std=gnu+11 etc.), and also I found some answers (http://stackoverflow.com/questions/17950814/how-to-use-stdstoul-and-stdstoull-in-android/18124627#18124627) which explains that ndk not supports new c++11 string function, so finally I implement to_string method as you suggests. Thanks :). – albciff Apr 01 '14 at 22:16
  • I have tried it but gives error on `std::ostringstream`. The issue might be about Android Studio 2.2 alpha 6. Is there any easy way to convert? – Onur Tuna Jul 27 '16 at 11:22
  • Extremely helpful all for compilers that don't support C++11. BTW: Is there a way (a macro definition) to check if C++11 is present, to skip this? – Wolf Sep 20 '17 at 09:56
  • I just found the char template specializations missing, you need 3 of them, for: char, signed char, unsigned char – Wolf Sep 20 '17 at 13:27
  • I have used the same function but application get crash for some devices with below log `libloglib-jni.so 0xdd7bdacf std::basic_ostringstream, std::allocator >::~basic_ostringstream() (basic_ios.h:276) 36 libart.so 0xf4832812 (Missing) 37 libloglib-jni.so 0xdd7a5851 std::string patch::to_string(int const&)` can you please provide any solution if you have. – Om Infowave Developers Nov 30 '17 at 12:09
  • I've updated the answer to account for modern NDKs, and also clarified the situations where the C++11 APIs were missing. – Dan Albert Jul 30 '18 at 21:53
  • Better to pass value by const reference: `std::string to_string(const T& value)` – Dmytro Jun 26 '19 at 21:00
26

With NDK r9+ you can use llvm-libc++ which offers full support for cpp11.

In your Application.mk you have to add:

APP_STL:=c++_static 

or

APP_STL:=c++_shared
kyb
  • 7,233
  • 5
  • 52
  • 105
thursdaysDove
  • 542
  • 7
  • 7
  • 2
    using cocos2d-x this worked to get around the std::to_string compile issue. However it caused other build problems down stream: "error: 'pthread_key_t' does not name a type static pthread_key_t s_threadKey" In case some tries this. I was never able to solve that. As mentioned here http://stackoverflow.com/questions/22164564/cannot-build-local-shared-library-in-android-ndk changing compilers led to other compile issues... The accepted answer got around the issue in the short term... – Hunter-Orionnoir Feb 23 '15 at 21:44
  • 1
    @Hunter I didn't mention that on my question however I was using cocos2d, and the accepted answer is simply an clean and as you said got around the issue so this is why I did accept it `:)` – albciff Feb 26 '15 at 17:58
  • Yes I too went with the accepted answer, I was not able to figure out exactly how to use this approach correctly. I was missing other threading libs. Probably could have done it if I spent more time... I just wanted that specific error here so if I ever run into this again I will have a hit right away :) – Hunter-Orionnoir Feb 27 '15 at 02:21
  • I was looking for this one for hours, so thank you thursdaysDove! – Kyone Jun 17 '15 at 18:20
  • I also get other errors down stream with this answer. – Jonny Jul 16 '15 at 01:15
  • @thursdaysDove, +1. Working fine when the flag added to the application.mk file. As expected i am able to compile from the terminal window using ndk-build. But i am not able to do this from eclipse (enable with android). There i am getting error on the to_string function. Do you have any idea which file need to be included? – Jeet Mar 22 '16 at 12:34
  • This breaks ABI compatibility with any static libraries compiled (e.g. third party libs). So you'll have to rebuild them again. Would be nice to avoid that. – void.pointer Jun 24 '16 at 16:17
13

Gradle

If you looking for solution for Gradle build system. Look at this answer.

Short answer.

Add the string

arguments "-DANDROID_STL=c++_shared"

in your build.gradle. Like

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {
        ...
        arguments "-DANDROID_STL=c++_shared"
      }
    }
  }
  ...
}
Community
  • 1
  • 1
kyb
  • 7,233
  • 5
  • 52
  • 105
  • 1
    Actually this is the only valid answer ,given that today's native development for Android is mostly done with Android Studio which uses Gradle. – Michael IV Apr 09 '18 at 14:42
1

Experimental Gradle Plugin

If you're looking for a solution for the Experimental Gradle plugin, this worked for me...

Tested with com.android.tools.build:gradle-experimental:0.9.1

model {
  ...
  android {
    ...
    ndk {
      ...
      stl = "c++_shared"
    }
  }
}
Community
  • 1
  • 1
stephenspann
  • 1,823
  • 1
  • 16
  • 31
0

I could not use c++_static, it gave some errors about undefined exceptions. So I returned to the gnustl_static.

But in NDK sources, in sources/cxx-stl/llvm-libc++/src/string.cpp, I found implementation of to_string(int) and tried to copy it to my code. After some corrections it worked.

So the final piece of code I had:

#include <string>
#include <algorithm>

using namespace std;


template<typename S, typename P, typename V >
inline
S
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
{
    typedef typename S::size_type size_type;
    size_type available = s.size();
    while (true)
    {
        int status = sprintf_like(&s[0], available + 1, fmt, a);
        if ( status >= 0 )
        {
            size_type used = static_cast<size_type>(status);
            if ( used <= available )
            {
                s.resize( used );
                break;
            }
            available = used; // Assume this is advice of how much space we need.
        }
        else
            available = available * 2 + 1;
        s.resize(available);
    }
    return s;
}

template <class S, class V, bool = is_floating_point<V>::value>
struct initial_string;

template <class V, bool b>
struct initial_string<string, V, b>
{
    string
    operator()() const
    {
        string s;
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, false>
{
    wstring
    operator()() const
    {
        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
          + 1;
        wstring s(n, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

template <class V>
struct initial_string<wstring, V, true>
{
    wstring
    operator()() const
    {
        wstring s(20, wchar_t());
        s.resize(s.capacity());
        return s;
    }
};

string to_string(int val)
{
    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
}
mortalis
  • 2,060
  • 24
  • 34
0

For Android Studio, add this in build.gradle (Mobile App)

externalNativeBuild {
    cmake {
        cppFlags "-std=c++11"

        arguments "-DANDROID_STL=c++_static"
    }
}