具有基元类型的模板向量类型
template vector type with primitive type
我想用基元类型(int
、float
、double
(和向量类型(vector<int>
、vector<float>
、vector<double>
(为函数模板。下面是我的代码。我想知道在构建不同的向量用例时,是否有一种方法可以用较少的代码重复来模板化parseKeyValue()
。谢谢
#include <iostream>
#include <typeinfo>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
using namespace std;
template<class T> T parseKeyValue(stringstream& ss){
T value;
while(ss >> value){};
return value;
}
template<> vector<string> parseKeyValue(stringstream& ss){
vector<string> value;
string item;
while(ss >> item) value.push_back(item);
return value;
}
template<> vector<int> parseKeyValue(stringstream& ss){
vector<int> value;
int item;
while(ss >> item) value.push_back(item);
return value;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v){
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(os, " "));
return os;
}
int main(){
stringstream ss("1-2-3 7-8-9");
vector<string> t = parseKeyValue< vector<string> >(ss);
cout << t << endl;
stringstream ss2("123 789");
vector<int> t2 = parseKeyValue< vector<int> >(ss2);
cout << t2 << endl;
stringstream ss3("123 789");
int t3 = parseKeyValue< int >(ss3);
cout << t3 << endl;
return 0;
}
您可以将其封装在类模板中,该模板可以是部分专用的。
template<class T>
struct Wrapper {
static T parseKeyValue(stringstream& ss){
T value;
while(ss >> value){};
return value;
}
};
template<class T>
struct Wrapper<std::vector<T>> {
static vector<T> parseKeyValue(stringstream& ss){
vector<T> value;
T item;
while(ss >> item) value.push_back(item);
return value;
}
};
template<class T> T parseKeyValue(stringstream& ss){
return Wrapper<T>::parseKeyValue(ss);
}
实时
或者应用带有模板重载的SFINAE。
template <typename T>
struct is_vector : std::false_type {};
template <typename T>
struct is_vector<std::vector<T>> : std::true_type {};
template<class T>
std::enable_if_t<!is_vector<T>::value, T>
parseKeyValue(stringstream& ss) {
T value;
while(ss >> value){};
return value;
}
template<class T>
std::enable_if_t<is_vector<T>::value, T>
parseKeyValue(stringstream& ss) {
T value;
typename T::value_type item;
while(ss >> item) value.push_back(item);
return value;
}
实时
根据定义函数的方式,您需要对函数进行部分专业化——这在C++中是不合法的。即使是合法的,您也没有用于推导模板类型的参数,因此您必须始终明确指定模板参数:
std::vector<int> v = parseKeyValue<std::vector<int>>(...);
// ^ ^ ^
因为从赋值到变量的推导是不可能的。
如果您将函数签名更改为填充函数参数,则可以使用重载操作:
template <typename T>
void parseKeyValue(T& t, std::istream& s);
template <typename T>
void parseKeyValue(std::vector<T>&, std::istream& s);
你甚至可以有一个通用容器的变体:
template <typename T, template <typename> class Container >
void parseKeyValue(Container<T>, std::istream& s);
请注意,我将参数从std::stringstream
更改为std::istream
,这限制较少,因此您也可以将函数与例如std::cin
一起使用。
这样,你就不依赖于部分专业化,并且可以从模板论证推导中额外获利:
int n;
parseKeyValue(n, std::cin); // selects non-container overload
std::vector<int> v;
parseKeyValue(v, std::cin); // selects vector overload, as more specialised
std::list<int> l;
parseKeyValue(l, std::cin); // selects generic container overload
旁注:
while(ss >> value){};
在您的原始非矢量版本中,将读取任何可用的值并丢弃除最后一个值之外的所有值。这是有意的吗?
相关文章:
- 基类类型向量中的派生结构
- 从自定义数据类型向量中删除重复元素
- C++:自定义数据类型向量错误的队列
- C++ - 按自定义数据类型向量的值删除元素
- 在 C++ 中创建类型向量
- 添加字符串向量和不同数据类型向量的映射
- 初始化一个类型向量的巨大向量<int>
- 没有操作员=的类型向量的实例化
- 复杂数据类型向量的迭代器
- 比较两个用户定义的类型向量
- 如何声明二维模板化类类型向量?
- 尝试将用户定义的向量类型插入用户定义的类型向量
- 类类型向量的打印内容
- 如何在 C++ 中将结构类型向量数据输入到结构向量成员(嵌套结构向量)中
- 如何使用新字符串而不是分配器创建自己的字符串类型向量?
- <T> 在使用运算符+ 连接两个向量之前从类型向量中删除索引
- 从自定义数据类型向量数组C 删除
- 如何打印类型向量<元组<字符串、int、int>> 以筛选 c++?
- 正在输出类型向量的成员类型
- 引用类类型向量中的对象成员