bl4ckb0ne
bl4ckb0ne

Reputation: 1227

Convert std::vector<std::string> to const char* const*

I'm working with Vulkan, and I'm trying to pass my validation layer as a vector<string>. But the field ppEnabledLayerNames from VkInstanceCreateInfo only takes const char* const*. I don't understand the type and how to convert my vector's data into it.

std::vector<std::string> v = {
    "VK_LAYER_LUNARG_standard_validation"
};

const char* const* data = std::accumulate(std::next(v.begin()), v.end(),
                                    v[0],
                                    [](std::string a, std::string b) {
                                        return a + b;
                                    }).c_str();

But when I compile, I got this :

error: cannot convert ‘const char*’ to ‘const char* const*’ in assignment
                     }).c_str();

Here's a live example

Upvotes: 2

Views: 3166

Answers (4)

bl4ckb0ne
bl4ckb0ne

Reputation: 1227

I finally found the solution this morning, using std::accumulate

auto d = std::accumulate(
    std::next(v.begin()), v.end(),
    v[0],
    [](std::string a, std::string b) {
        return a + b;
    }).c_str();

const char* const* data = &d;

Upvotes: 0

Ap31
Ap31

Reputation: 3324

This is what you're doing in your snippet:

  • concatenate all the strings in v (or crash if v is empty);
  • throw away the resulting string;
  • try to assign a dangling pointer to const char to const char* const*.

The last part did not compile, but that's a good thing - dealing with this in a runtime would be a sad expirience.

By the looks of the interface (namely the ppEnabledLayerNames parameter) one could guess that you don't want to concatenate the strings in the first place, but instead you want to pass an array of c-strings.

Here is how to get it from vector<string>:

vector<const char*> layer_names(v.size());
std::transform(v.begin(), v.end(), layer_names.begin(), [](const string& s)
             { return s.c_str(); });
const char* const* data = layer_names.data(); 

Notice that it will only be valid until either layer_names or v is destroyed.

The better way would be to find a C++-friendly interface for Vulkan, I can't help with that though.

Upvotes: 0

David Kennedy
David Kennedy

Reputation: 380

With c_str you will get const char*. A const char* const* is an array of const char*.

  vector<string> vectorOfStrings = {
    "Aa", 
    "Bb", 
    "Cc"
  };

  vector<const char*> vectorOfCStyleStrings(3);

  // convert from string to C style strings
  for (string item : vectorOfStrings)
    vectorOfCStyleStrings.push_back(item.c_str());

  // get vector like a const C style array
  const char* const* arrayOfCStyleStrings = vectorOfCStyleStrings.data();

Upvotes: 3

tadman
tadman

Reputation: 211680

Here's a way to do it on a std::string:

const std::string str = "test";
const char* str_p = str.c_str();

const char* const* ppEnabledExtensionNames = &str_p;

Be careful if c_str() is part of a temporary string that's getting trashed. You may need to retain a reference to the base string object until you're done with this.

Upvotes: 2

Related Questions