我喜欢 vector ,通常在数组上使用它们。因此,我创建了一个模板化可变参数函数来初始化 vector (包括在下面)。
header (.h):
template <typename T>
vector<T> initVector(const int argCount, T first, ...);
来源(.hpp):
template <typename T>
vector<T> initVector(const int argCount, T first, ...) {
vector<T> retVec;
retVec.resize(argCount);
if(argCount < 1) { ... }
retVec[0] = first;
va_list valist;
va_start(valist, first);
for(int i = 0; i < argCount-1; i++) { retVec[i+1] = va_arg(valist, T); }
va_end(valist);
return retVec;
}
它适用于大多数类型(例如int,double ...),但不适用于字符串-编译器将其解释为“const char *”,因此
vector<string> strvec = initVector(2, "string one", "string two");
给我错误:
error: conversion from ‘std::vector<const char*, std::allocator<const char*> >’ to non-scalar type ‘std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ requested
有什么方法可以将字符串参数解释为字符串而不必强制转换每个字符串?
最佳答案
因为常量"string one"
的类型是const char*
而不是std::string
,所以需要进行转换。 va_arg
无法进行此转换,因此我们需要第二个模板参数:
template <typename VecT, typename EleT>
std::vector<VecT> init_vector(const size_t nargs, EleT first, ...) {
std::vector<VecT> result;
result.reserve(nargs);
if (nargs == 0) {
return result;
}
result.push_back(first);
if (nargs == 1) {
return result;
}
va_list valist;
va_start(valist, first);
for (int i = 1; i < nargs; ++i) {
result.push_back(VecT(va_arg(valist, EleT)));
}
va_end(valist);
return result;
}
std::vector<std::string> = init_vector<std::string>(2, "string one", "string two")
请注意,我进行了一些更改,尤其是将
resize
更改为reserve
,以防止创建不必要的对象。您也可以简单地使用它(不弄乱元素数量,并输入安全类型):
const char *args[] = {"string one" , "string two"};
std::vector<std::string> strvec(args, args + sizeof(args)/sizeof(args[0]))
或使用C++ 11初始化程序列表:
std::vector<std::string> strvec = {"string one" , "string two"};
为了好玩,我做了一件小巧的事情,它变得更加整洁和安全,但并没有泛泛到任意数量的参数上。它通过重载来工作。以下是前三个重载和示例用法:
template<class C>
inline C init_container() {
return C();
}
template<class C, class T>
inline C init_container(T arg0) {
const T args[1] = {arg0};
return C(args, args + 1);
}
template<class C, class T>
inline C init_container(T arg0, T arg1) {
const T args[2] = {arg0, arg1};
return C(args, args + 2);
}
std::vector<std::string> vec =
init_container< std::vector<std::string> >("hello", "world");
完整的 header (最多100个参数)可以在此处下载:https://gist.github.com/3419369。