将矢量转换为<string>其他类型的
Convert vector<string> to other types
我有一个map<string,vector<string>>
类。我想给用户一个成员函数,以接收与 std::vector(字符串( 不同格式的键的值:
向量(字符串(, 字符串 向量, 向量(浮点数(和 布尔
例:
bool x = (bool) myClass["dummy_boolean_type"]
x = myClass["dummy_boolean_type"].as<bool>
int y = (int) myClass["dummy_boolean_type"]
有人可以举一个例子,实现它的最佳方法是什么?(在加速中不使用(
不能为类提供任何一个或多个成员函数这将支持您想要的两个构造:
T x = myClassInstance["key"].as<T> // (1)
T x = (T) myClassInstance["key"] // (2)
在(1(的情况下,直接原因只是结构是不是合法C++。因此,假设它被替换为:
T x = myClassInstance["key"].as<T>() // (1a)
但这无济于事,(1a(和(2(的原因相同:
表达式myClassInstance["key"]
必须计算为某些对象e
或引用,这些对象由以下人员返回:
myClass::operator[](std::string const &);
此e
是key
映射到的vector<string>
map<string,vector<string>
myClass
的数据成员。它不是 myClassInstance
.
所以你要求的myClass
的成员函数将支持结构:
T x = e.as<T> // (1b)
T x = (T) e // (2b)
其中e
是std::vector<std::string>
.
显然,您在myClass
中无法满足您的要求。在(1b(和(2b(,myClass
无处可见。
std::vector<std::string>
有没有模板成员函数:
template<typename T>
T as() const;
具有您想要的行为 (1b(?
std::vector<std::string>
是否有任何模板成员函数:
template<typename T>
operator T() const;
具有您想要的行为 (2b(?
不,不。
然而。。。
您可以实现myClass
的as
模板成员函数支持您提到的转换。它的签名 - 当然 -将:
template<typename T>
T myClass::as(std::string const & key) const;
你会像这样调用它:
T x = myClassInstance.as<T>("key") // (1c)
我将勾勒出一个实现,假设我们对从std::vector<std::string>
转换为:
-
std::string
-
std::vector<int>
-
bool
这足以让你开始。
要将std::vector<std::string> vs
转换为std::string
我将连接vs
的元素 .
要将std::vector<std::string> vs
转换为std::vector<int>
我将vs
的每个元素从十进制数字(如果可以(转换为数字表示的整数,并返回这些整数的向量。没有对其他政策的偏见,我会抛出一个std::invalid_argument
例外当元素未修剪为十进制数字时。
对于转换std::vector<std::string>
可能意味着什么,我被宠坏了到bool
,所以我会武断地说vs
是true
如果我能转换它到任何元素都不是 0 并且false
的vector<int>
,如果我可以转换它到一个所有元素均为 0 的vector<int>
。
草图:
#include <type_traits>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
namespace detail {
template<typename T>
struct convert_to
{
static T from(std::vector<std::string> const & vs) {
static constexpr bool always_false = !std::is_same<T,T>::value;
static_assert(always_false,
"Calling `convert_to<T>::from` for unimplemented `T`");
return *(T*)nullptr;
}
};
template<>
std::string convert_to<std::string>::from(std::vector<std::string> const & vs)
{
std::string s;
for ( auto const & e : vs ) {
s += e;
}
return s;
}
template<>
std::vector<int>
convert_to<std::vector<int>>::from(std::vector<std::string> const & vs)
{
auto lamb = [](std::string const & s) {
std::size_t lastoff = s.find_last_not_of(" tfvnr");
int i;
try {
std::size_t nlen;
i = std::stoi(s,&nlen);
if (nlen <= lastoff) {
throw std::invalid_argument("");
}
}
catch(std::invalid_argument const & e) {
throw std::invalid_argument(
"Cannot convert "" + s + "" to int");
}
return i;
};
std::vector<int> vi;
std::transform(vs.begin(),vs.end(),std::back_inserter(vi),lamb);
return vi;
}
template<>
bool convert_to<bool>::from(std::vector<std::string> const & vs)
{
auto vi = convert_to<std::vector<int>>::from(vs);
for (auto const & i : vi) {
if (i) {
return true;
}
}
return false;
}
} // namespace detail
struct myClass // Your class
{
// Whatever...
std::vector<std::string> & operator[](std::string const & key) {
return _map[key];
}
template<typename T>
T as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
// Whatever...
private:
std::map<std::string,std::vector<std::string>> _map;
};
这里的一个要点是使用 template<typename T>
detail::struct convert_to
及其孤立静态成员函数:
T from(std::vector<std::string> const & vs)
在默认实例化中会导致static_assert
失败报告未从std::vector<std::string>
转换为T
定义。
然后,对于要转换为的每种类型U
,您只需写一个专门的定义:
template<>
U convert_to<U>::from(std::vector<std::string> const & vs);
如您认为合适,结构 (1c( 将按照以下方式使用它:
template<typename T>
T myClass::as(std::string const & key) {
return detail::convert_to<T>::from(_map[key]);
}
以下是您可以附加到草图的说明性程序:
#include <iostream>
using namespace std;
template<typename T>
static void print_vec(std::vector<T> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << e << " ";
}
cout << "}n";
}
static void print_vec(std::vector<std::string> const & v)
{
cout << "{ ";
for (auto const & e : v) {
cout << '"' << e << "" ";
}
cout << "}n";
}
int main()
{
myClass f;
f["int_vec"] = vector<string>{"0","1 "," 2"};
cout << "f["int_vec"] = "; print_vec(f["int_vec"]);
f["true_vec"] = vector<string>{"0"," 1 ","0"};
cout << "f["true_vec"] = "; print_vec(f["true_vec"]);
f["false_vec"] = vector<string>{"0"," 0","0 "};
cout << "f["false_vec"] = "; print_vec(f["false_vec"]);
f["not_int_vec0"] = vector<string>{"0","1","2",""};
cout << "f["not_int_vec0"] = "; print_vec(f["not_int_vec0"]);
f["not_int_vec1"] = vector<string>{"0","@","2",};
cout << "f["not_int_vec1"] = "; print_vec(f["not_int_vec1"]);
f["not_int_vec2"] = vector<string>{"0"," 1$","2",};
cout << "f["not_int_vec2"] = "; print_vec(f["not_int_vec2"]);
cout << "f.as<string>("int_vec") = ""
<< f.as<string>("int_vec") << '"' << endl;
cout << "f.as<string>("true_vec") = ""
<< f.as<string>("true_vec") << '"' << endl;
cout << "f.as<string>("false_vec") = ""
<< f.as<string>("false_vec") << '"' << endl;
cout << "f.as<string>("not_int_vec0") = ""
<< f.as<string>("not_int_vec0") << '"' << endl;
cout << "f.as<string>("not_int_vec1") = ""
<< f.as<string>("not_int_vec1") << '"' << endl;
cout << "f.as<string>("not_int_vec2") = ""
<< f.as<string>("not_int_vec2") << '"' << endl;
vector<int> va = f.as<vector<int>>("int_vec");
cout << "f.as<vector<int>>("int_vec") = ";
print_vec(f.as<vector<int>>("int_vec"));
cout << boolalpha << "f.as<bool>("true_vec") = "
<< f.as<bool>("true_vec") << endl;
cout << boolalpha << "f.as<bool>("false_vec") = "
<< f.as<bool>("false_vec") << endl;
try {
cout << "f.as<vector<int>>("not_int_vec0")...";
auto b = f.as<vector<int>>("not_int_vec0");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>("not_int_vec1")...";
auto b = f.as<vector<int>>("not_int_vec1");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
try {
cout << "f.as<vector<int>>("not_int_vec2")...";
auto b = f.as<vector<int>>("not_int_vec2");
(void)b;
}
catch(std::invalid_argument const & e) {
cout << e.what() << endl;
}
// char ch = f.as<char>("int_vec"); <- static_assert fails
return 0;
}
它输出:
f["int_vec"] = { "0" "1 " " 2" }
f["true_vec"] = { "0" " 1 " "0" }
f["false_vec"] = { "0" " 0" "0 " }
f["not_int_vec0"] = { "0" "1" "2" "" }
f["not_int_vec1"] = { "0" "@" "2" }
f["not_int_vec2"] = { "0" " 1$" "2" }
f.as<string>("int_vec") = "01 2"
f.as<string>("true_vec") = "0 1 0"
f.as<string>("false_vec") = "0 00 "
f.as<string>("not_int_vec0") = "012"
f.as<string>("not_int_vec1") = "0@2"
f.as<string>("not_int_vec2") = "0 1$2"
f.as<vector<int>>("int_vec") = { 0 1 2 }
f.as<bool>("true_vec") = true
f.as<bool>("false_vec") = false
f.as<vector<int>>("not_int_vec0")...Cannot convert "" to int
f.as<vector<int>>("not_int_vec1")...Cannot convert "@" to int
f.as<vector<int>>("not_int_vec2")...Cannot convert " 1$" to int
(GCC 5.1, Clang 3.6, C++11(
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- std中有类似find_last_of的函数,而string中没有
- EASTL矢量<向量<int>>连续的
- 使用 std::string () const 函数启动线程或未来
- 使用char类型将decimal转换为string,将string转换为decimal
- 迭代和比较映射<字符串、矢量<string>> c++ 中的值
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 将向量解析<string>为字符串
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 如何更改大小(std::string)
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- C++:如何将 unix 时间的字符串转换为 *tm?(使用时间错误:"cannot convert 'String' to 'tm*' ")
- std::string 的对象真的可以移动吗?
- 与'operator='不匹配(操作数类型'String'且"void")
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- <string> 使用 for 循环写入向量