Постоянный символьный указатель с использованием unique_ptr

Допустим, у меня есть vector<string> input и мне нужно передать это функции, которая принимает const char** аргумент. Моя мысль состояла в том, чтобы использовать unique_ptr как это:

const auto output = make_unique<char*>(size(input));

Но я не могу повернуть const unique_ptr<const*> в const char**, Есть ли способ сделать это, или, возможно, более простая альтернатива?

2

Решение

Я бы просто построил вектор указателей на c_str()из строк, а затем получить указатель на это.

std:vector<const char*> pointers;
pointers.reserve(input.size());
for (const auto& e : input)
pointers.push_back(e.c_str()); // get const char *'s
auto argument = pointers.data(); // get pointer to const char*'s - const char**

Или используя unique_ptr

auto pointers = std::make_unique<const char*[]>(size(input))
for (size_t i = 0; i < input.size(); ++i)
pointers[i]= input[i].c_str(); // get const char *'s
auto argument = pointers.get(); // get pointer to const char*'s - const char**
3

Другие решения

Я предполагаю, что вам это нужно, чтобы соответствовать какому-либо интерфейсу, которым вы не управляете, в противном случае я бы рассмотрел адаптацию рассматриваемого интерфейса, чтобы избежать ненужного создания временных данных только для подгонки плохо приспособленного интерфейса…

Поскольку вам просто нужен временный массив известного размера, простейшим решением, вероятно, будет выделение массива указателей и заполнение его указателями на строки в вашем векторе:

auto pointers = std::make_unique<const char*[]>(size(v));
std::transform(begin(v), end(v), &pointers[0], [](const auto& s) { return s.c_str(); });

Этот массив также может быть помещен в стек, чтобы избежать динамического выделения памяти. Но так как вы работаете со строками здесь и хотите копировать данные во временный массив, я предполагаю, что производительность не критична, поэтому я полагаю, что нет необходимости в дополнительной сложности …

3

два подхода, в зависимости от того, требует ли интерфейс c нулевого завершения или нет:

#include <vector>
#include <string>
#include <algorithm>

auto make_c_interface_null_terminated(std::vector<std::string> const &input) -> std::vector<const char*>
{
auto result = std::vector<const char*>(input.size() + 1);
auto to_c_str = [](auto&& str) { return str.c_str(); };
std::transform(begin(input), end(input), begin(result), to_c_str);
// implied:  result[result.size() - 1] = nullptr
return result;
}

auto make_c_interface(std::vector<std::string> const &input) -> std::vector<const char*>
{
auto result = std::vector<const char*>(input.size());
auto to_c_str = [](auto&& str) { return str.c_str(); };
std::transform(begin(input), end(input), begin(result), to_c_str);
return result;
}extern "C" void c_interface_requires_null(const char** argv);
extern "C" void c_interface_sized(size_t size, const char** args);void test(std::vector<std::string> const &input)
{
auto output1 = make_c_interface_null_terminated(input);
c_interface_requires_null(output1.data());

auto output2 = make_c_interface(input);
c_interface_sized(output1.size(), output1.data());
}
1
А ты уже прошел курс программирования? Супер скидка!
Прокачать скилл $$$
×