【问题标题】:C++ better way to emplace char* strings into a std::vector<string>?C++ 将 char* 字符串放入 std::vector<string> 的更好方法?
【发布时间】:2019-01-22 00:08:28
【问题描述】:

我正在从任何一个填充字符串向量 字符[] 字符* 标准::字符串 通过将它们放置在 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\0", 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 char* 的情况 我决定跳过它而不是创建一个空字符串。

我对 nullptr 进行了 try/catch,但发现没有必要使用 模板。

【问题讨论】:

  • 有关代码有效但您希望更好地工作的问题应该在Code Review 提出。是的,我链接到如何询问页面。如果您不熟悉 Code Review,那么这是最好的起点。
  • d 不是以零结尾的,所以 safe_emplace(svec, d); 是 UB。
  • "特别想处理 NULL char*" - 那么我建议为 char* 提供 safe_emplace() 的重载。

标签: c++ variadic emplace


【解决方案1】:

此代码有效,但看起来有点笨拙,需要三个模板来涵盖可变参数和初始化列表。

这种事情有更规范的成语吗?

并非如此,因为您必须分别处理可变参数模板和initializer_list

我特别想处理 NULL char* 的情况 我决定跳过它而不是创建一个空字符串。

那么您应该提供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;
}

Live Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 2011-10-26
    相关资源
    最近更新 更多