For those who also deal with lack of std::transform in pre-C++17-20 standards: in continuation of the excellent solution https://stackoverflow.com/a/74813820/30971218, I am attaching my own functions with 'for-each' loop:
std::vector<char *> conv2vect (std::vector<std::string> const & inp_vect)
{
std::vector<char *> outp_vect;
for (auto const & el : inp_vect)
{
outp_vect.push_back(const_cast<char *>(el.c_str()));
}
return outp_vect;
}
This fine suitable for C API functions where you need to provide a non-const Pointer-2-Pointer (if you need a std::vector<char const *> for char const ** input arg, simple remove a const_cast<>; I used it only because std::string::data(), as std::string::c_str() (as described in https://stackoverflow.com/questions/74813679/how-to-pass-a-vector-of-strings-to-a-function-with-a-c-style-pointer-to-c-string#comment132036577_74813820), returns const internal buffer before C++17). Note: because of 'for-each' loop specific, iterator must be reference; in case of by-value access (auto el : inp_vect) output will be garbage, because of destruction of std::string's temporary objects, and, as a consequence, internal char array (requested with str->c_str()).
Const-analogue (if char const ** needed):
std::vector<char const *> conv2vect_const (std::vector<std::string> const & inp_vect)
{
std::vector<char const *> outp_vect;
for (auto const & el : inp_vect)
{
outp_vect.push_back(el.c_str());
}
return outp_vect;
}
And lambda-analogue:
auto conv2vect_lambda = []
( std::vector<std::string> const & inp_vect )
-> std::vector<char *>
{
std::vector<char *> outp_vect;
for (auto const & el : inp_vect)
{
outp_vect.push_back(const_cast<char *>(el.c_str()));
}
return outp_vect;
};
For 'more' C++ and RAII-principles fit, to emphasize of that we deal with references on temporaries in our 'converted' vector, we can use a RAII smart-pointer return:
std::unique_ptr<std::vector<char *>> conv2smart_ptr (
std::vector<std::string> const & inp
)
{
// before C++14 and 'make_unique'..
std::vector<char *> * tv = new std::vector<char *>{};
for (auto const & el : inp){
tv->push_back(const_cast<char *>(el.c_str()));
}
return std::unique_ptr<std::vector<char *>>{tv};
}
Call example:
void foo(char ** pp, size_t size_of_pp);
void foo_const(char const ** pp, size_t size_of_pp); // some 'C' functions
std::vector<std::string> vect{"abc","def"}; // input vector to 'converting'
//1
std::vector<char *> v = conv2vect(vect);
foo(v.data(), v.size());
//2
std::vector<char const *> v_const = conv2vect_const(vect);
foo_const(v_const.data(), v_const.size());
//3
v = conv2vect_lambda(vect);
foo(v.data(), v.size());
//4
std::unique_ptr<std::vector<char *>> smart_ptr_v = conv2smart_ptr(vect);
foo(smart_ptr_v->data(), smart_ptr_v->size());