'Cast an array of strings to an array of char*
I'm trying to get rid of the ISO C++ forbids converting a string constant to ‘char*’ warning, my code looks like the following:
char* var[] = {"abc", "def"};
// many more lines like this ...
One solution is to prepend each string literal with (char*) however that's ugly and unmaintainable. Ideally I'd like to be able to edit these lines to say
char* var[] = array_cast<char*>({"abc", "def"});
I found a solution here for almost the same problem except it deals with std::array instead of plain C arrays and array variables rather than initializer lists.
I want to avoid using std::array, std::string, const char*, std::vector since the functions that eventually get called accept non-const char**.
Solution 1:[1]
I have arrived at a solution. It requires two arrays one of which needs to be cleaned up afterwards so it can surely be improved.
template<size_t N, size_t... Is>
constexpr char**
array_cast(const std::array<const char*, N>& arr, std::index_sequence<Is...>)
{
return new char*[]{const_cast<char*>(std::get<Is>(arr))...};
}
template<size_t N>
constexpr char**
array_cast(const std::array<const char*, N>& arr)
{
return array_cast(arr, std::make_index_sequence<N>());
}
const std::array var {"abc", "def"};
char** result = array_cast(var);
Solution 2:[2]
C string literals are constant and will be placed in the .data section and protected from being modified by the hardware. No amount of casting will fix that.
C++ strings (std::string) are mutable so use those:
#include <string>
using namespace std::literals;
std::string var[] = {"abc"s, "def"s};
Although why you would want mutable strings in an array escapes me.
Solution 3:[3]
"abc" and "def" are string literals of type const char[4] which decays to const char*(and not char*) due to type decay.
So you need to add a low-level const indicating that var is an array of pointers to const char(instead of pointer to char) as shown below:
const char* var[] = {"abc", "def"};
Or better yet use std::array or std::vector with elements of type std::string.
std::vector<std::string> var{"abc", "def"};
Solution 4:[4]
As a possible workaround, it would be possible to use two arrays, one with std::string objects, and one with char* pointers to the strings in the first array:
std::array<std::string, 2> real_strings = {{ "foo", "bar" }};
char* wrap[] = { &real_strings[0][0], &real_strings[1][0] };
This can of course be used together with a vector and dynamic allocation and a loop to initialize the wrapper array, if the number of strings is not known at compile-time (or may change at run-time).
On a personal note, to me it all seems like a design flaw in the API you're using.
Solution 5:[5]
You can create a modifiable 2d array of chars like this:
char var[][4] = {"abc", "def"};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | kryphon |
| Solution 2 | Goswin von Brederlow |
| Solution 3 | Anoop Rana |
| Solution 4 | Some programmer dude |
| Solution 5 | eerorika |
