将Std::string转换为std::array?

13

如何将字符串转换成数组?我需要像这样的结果:

template<class T, size_t N, class V>
std::array<T, N> to_array(const V& v)
{
    assert(v.size() == N);
    std::array<T, N> d;
    std::copy(v.begin(), v.end(), d.data());
    return d;
}

C++11或Boost是否提供类似的功能?其他人是如何做到这一点的?每次在项目中需要该函数时,复制/粘贴此函数似乎很傻。

6
放在标题里面? - R. Martinho Fernandes
我有一个包含大约一百万个20(或32)字节键的映射表,我想避免使用std::string所需的额外分配和间接引用。 - XTF
1
这是关于std::array,而不是std::vector。 - XTF
它看起来并不是很有用;如果您在编译时知道您的数据长度为20或32字节,为什么要通过字符串传递它呢? - JoeG
@ViktorSehr d[v.size()] 是越界访问。字符串的大小是精确的,有一个断言记录了这一点。 - R. Martinho Fernandes
显示剩余4条评论
5个回答

6

看起来不错。在C++11中没有这样的东西,我认为Boost中也没有。如果你不想把这个东西到处粘贴,你可以把它放在一个头文件中,然后#include它。


3
每个项目都需要这个吗?我认为它有特定的使用场景。这也正是为什么你在C++11或boost中找不到它的原因:它并不是一个基本的东西。 - R. Martinho Fernandes
3
通常来说,当一个公司有一系列的项目时,会将它们放在一个物理目录层次结构下,并使用共同的库。专业人士不会将他们想要使用的 boost 文件从一个项目复制到另一个项目;他们只有一个 boost 的副本,并在所有项目中都从同一个位置使用。同样地,如果你有一个实用程序库头文件并且其中包含了这个函数,你也不需要将它复制到每个项目中,而是在一个特定的位置使用同一个头文件。这样,如果你需要修复一个函数或进行更新,你就不需要处理代码分歧和多次修复缺陷问题。 - ex0du5
@XTF:为什么两个不相关的项目需要这段几乎毫无意义的代码? - ildjarn
@Martinho:不是的,但它似乎是一项基本功能。像列表和向量这样的容器支持从迭代器对进行简单构造。我无法想象只有我在使用它。 - XTF
@XTF:“但不适用于无关项目,也不适用于公司。” 即使是针对个人项目,每个人都有自己的小型实用程序和便利函数库。这并不难做。只需创建一个包含此类内容的项目目录即可。无需复制或进行任何类似的操作。 - Nicol Bolas
显示剩余5条评论

5

只需简单地调用:

std::copy(v.begin(), v.end(), d.data());

将字符串转换为数组的方法是使用 split 函数。我不认为把它包装成一个专用的“实用”函数有任何优势。

另外,除非编译器进行了优化,否则您的功能性能可能会降低:在返回数组时,数据将被复制第二次。


当你想直接将数组传递给函数时,就不能使用它。 - XTF

1
如果您只想将字符串转换为数组,只需使用 .c_str()(并处理 char*)。虽然它不完全是 array<>,但可能适合您的需求。

1
不,它不符合我的需求,因为那是一个引用,而我需要的是一个值。 - XTF

1

没问题,也许只需要对C++11进行微小的修改。

template<class T, size_t N, class V>
std::array<T, N> to_array(const V& v)
{
    assert(v.size() == N);
    std::array<T, N> d;
    using std::begin; using std::end; 
    std::copy( begin(v), end(v), begin(d) ); // this is the recommended way
    return d;
}

这样,如果您删除断言,即使v是原始数组,此函数也可以正常工作。


这是C++11特有的。在这种情况下可能没问题。你确定它是std::begin()而不仅仅是begin()吗?你的代码将会在那些在其自己命名空间中有自由begin()的类中失败。 - XTF
3
建议使用 using std::begin; using std::end; std::copy(begin(v), end(v), begin(d)); - bames53
@XTF 那不是我写的版本,我没有放置命名空间,因为名称查找应该仍然有效。但是,我相信bames53的建议使其完全通用,当它是std容器时使用std,而当它不是时使用特定的(如果找到)。 - Klaim
1
添加额外的 using std::begin; using std::end; 使 to_array 真正通用。如果使用 std::begin(v),则会阻止容器 T 覆盖 begin()。底线是,你需要额外的行来让 Koenig 解析执行其应该执行的操作! - Sean

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接