C++ 将 char* 字符串放入 std::vector<string> 的更好方法?
C++ better way to emplace char* strings into a std::vector<string>?
我正在从任何一个填充一个字符串向量
字符[]
字符*
std::string
通过将它们放置在 std::vector
此代码有效,但看起来有点笨拙,需要三个模板来涵盖可变参数和初始化列表。
有没有比这更规范的成语?
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <stdexcept>
// safe function for putting char* strings into a std::vector<std::string>
template <typename T, typename C>
std::vector<T> & safe_emplace( std::vector<T>& vec, C& c)
{
if ( !c ) return vec;
vec.emplace_back(c);
return vec;
}
// variadic version
template <typename T, typename C, typename... Args>
std::vector<T> & safe_emplace( std::vector<T>& vec, C& c, Args... args)
{
safe_emplace(vec, c);
return safe_emplace( vec, args...);
}
// initializer list version
template <typename T>
std::vector<T> & safe_emplace( std::vector<T>& vec, const std::initializer_list<std::string> il)
{
for (auto& s: il)
vec.emplace_back(s);
return vec;
}
int main( int argc, char* argv[])
{
std::vector<std::string> svec;
char one[] = "string one";
char two[] = "string two";
char three[] = "string three";
char* d = new char[10];
char* n = NULL;
std::strncpy(d, "0123456789[=12=]", 10);
safe_emplace(svec, one); // char[]
safe_emplace(svec, two, three); // variadic
safe_emplace(svec, d); // char*
safe_emplace(svec, n); // char* NULL
safe_emplace(svec, "five", "four", "three", "two", "one", nullptr);
safe_emplace(svec, {"A", "B", "C", "D", "E"} );
for (auto s : svec)
std::cout << s << "\n";
delete[] d; // clean up d (new)
return 0;
}
我特别想处理 NULL 字符的情况*
我决定跳过它而不是创建一个空字符串。
我有一个 try/catch 用于 nullptr,但发现没有必要
模板。
This code works but is a bit clunky looking and takes three templates to cover variadics and initializer lists.
Is there a more canonical idiom for this kind of thing?
不一定,因为您必须单独处理可变模板和 initializer_list
。
I specifically wanted to handle the case of a NULL char*
which I decided to skip it instead of create an empty string.
那么您应该提供 safe_emplace()
的重载以将 char*
数据与其他类型分开处理。
尝试更像这样的东西:
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
// rename the actual emplacement functions to avoid unwanted
// recursive loops in the variadic template iteration...
template <typename Container>
Container& do_safe_emplace(Container &c, const char *value)
{
if (value) c.emplace_back(value);
return c;
}
template <typename Container>
Container& do_safe_emplace(Container &c, const typename Container::value_type &value)
{
c.emplace_back(value);
return c;
}
// this overload is needed to handle when 'args...' becomes blank
// at the end of the variadic template loop iteration...
template <typename Container>
Container& safe_emplace(Container &c)
{
return c;
}
template <typename Container, typename T, typename... Args>
Container& safe_emplace(Container &c, const T &value, Args... args)
{
do_safe_emplace(c, value);
return safe_emplace(c, args...);
}
template <typename Container, typename T>
Container& safe_emplace(Container &c, const std::initializer_list<T> il)
{
for (auto& value: il)
do_safe_emplace(c, value);
return c;
}
int main()
{
std::vector<std::string> svec;
char one[] = "string one";
char two[] = "string two";
char three[] = "string three";
std::string four = "string four";
char* d = new char[11]; // <- need room for null terminator
char* n = NULL;
std::strncpy(d, "0123456789", 11);
safe_emplace(svec, one); // char[]
safe_emplace(svec, two, three, four); // variadic
safe_emplace(svec, d); // char*
safe_emplace(svec, n); // char* NULL
safe_emplace(svec, "five", "four", std::string("three"), "two", "one", nullptr);
safe_emplace(svec, {"A", "B", "C", "D", "E"} );
for (auto &s : svec)
std::cout << s << "\n";
delete[] d; // clean up d (new)
return 0;
}
我正在从任何一个填充一个字符串向量 字符[] 字符* std::string 通过将它们放置在 std::vector
此代码有效,但看起来有点笨拙,需要三个模板来涵盖可变参数和初始化列表。
有没有比这更规范的成语?
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <stdexcept>
// safe function for putting char* strings into a std::vector<std::string>
template <typename T, typename C>
std::vector<T> & safe_emplace( std::vector<T>& vec, C& c)
{
if ( !c ) return vec;
vec.emplace_back(c);
return vec;
}
// variadic version
template <typename T, typename C, typename... Args>
std::vector<T> & safe_emplace( std::vector<T>& vec, C& c, Args... args)
{
safe_emplace(vec, c);
return safe_emplace( vec, args...);
}
// initializer list version
template <typename T>
std::vector<T> & safe_emplace( std::vector<T>& vec, const std::initializer_list<std::string> il)
{
for (auto& s: il)
vec.emplace_back(s);
return vec;
}
int main( int argc, char* argv[])
{
std::vector<std::string> svec;
char one[] = "string one";
char two[] = "string two";
char three[] = "string three";
char* d = new char[10];
char* n = NULL;
std::strncpy(d, "0123456789[=12=]", 10);
safe_emplace(svec, one); // char[]
safe_emplace(svec, two, three); // variadic
safe_emplace(svec, d); // char*
safe_emplace(svec, n); // char* NULL
safe_emplace(svec, "five", "four", "three", "two", "one", nullptr);
safe_emplace(svec, {"A", "B", "C", "D", "E"} );
for (auto s : svec)
std::cout << s << "\n";
delete[] d; // clean up d (new)
return 0;
}
我特别想处理 NULL 字符的情况* 我决定跳过它而不是创建一个空字符串。
我有一个 try/catch 用于 nullptr,但发现没有必要 模板。
This code works but is a bit clunky looking and takes three templates to cover variadics and initializer lists.
Is there a more canonical idiom for this kind of thing?
不一定,因为您必须单独处理可变模板和 initializer_list
。
I specifically wanted to handle the case of a NULL char* which I decided to skip it instead of create an empty string.
那么您应该提供 safe_emplace()
的重载以将 char*
数据与其他类型分开处理。
尝试更像这样的东西:
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
// rename the actual emplacement functions to avoid unwanted
// recursive loops in the variadic template iteration...
template <typename Container>
Container& do_safe_emplace(Container &c, const char *value)
{
if (value) c.emplace_back(value);
return c;
}
template <typename Container>
Container& do_safe_emplace(Container &c, const typename Container::value_type &value)
{
c.emplace_back(value);
return c;
}
// this overload is needed to handle when 'args...' becomes blank
// at the end of the variadic template loop iteration...
template <typename Container>
Container& safe_emplace(Container &c)
{
return c;
}
template <typename Container, typename T, typename... Args>
Container& safe_emplace(Container &c, const T &value, Args... args)
{
do_safe_emplace(c, value);
return safe_emplace(c, args...);
}
template <typename Container, typename T>
Container& safe_emplace(Container &c, const std::initializer_list<T> il)
{
for (auto& value: il)
do_safe_emplace(c, value);
return c;
}
int main()
{
std::vector<std::string> svec;
char one[] = "string one";
char two[] = "string two";
char three[] = "string three";
std::string four = "string four";
char* d = new char[11]; // <- need room for null terminator
char* n = NULL;
std::strncpy(d, "0123456789", 11);
safe_emplace(svec, one); // char[]
safe_emplace(svec, two, three, four); // variadic
safe_emplace(svec, d); // char*
safe_emplace(svec, n); // char* NULL
safe_emplace(svec, "five", "four", std::string("three"), "two", "one", nullptr);
safe_emplace(svec, {"A", "B", "C", "D", "E"} );
for (auto &s : svec)
std::cout << s << "\n";
delete[] d; // clean up d (new)
return 0;
}