I want to create a function Vec2()
for the follow input:
string in="[[">>v","v^<","<><"],[">>v","v^<","<><"]]"
it should return
{{">>v","v^<","<><"},{">>v","v^<","<><"}}
It works fine in single string version,in that case ,stringToVecStr()
gives the correct answer.
ie: [">>v","v^<","<><"]
->{">>v","v^<","<><"}
But for Vec2()
it errors out:
'std::vector<std::vector<std::string, std::allocator<std::string>>, std::allocator<std::vector<std::string, std::allocator<std: :string>>>>::push_back':
no overloaded function could convert all the argument types temp C:\Users\mingy\source\repos\temp\temp\Source.cpp 72
What does this mean and where should I modify it?
Here is a minimal reproducible example:
#include<iostream>
#include<string>
#include<type_traits>
#include<fstream>
#include<vector>
#include<regex>
#include<sstream>
using namespace std;
inline string stringToVecStr(const string input) {
string result;
for (int i = 1; i < input.length() - 1; i ) {
char currentChar = input[i];
if (input[i] == '\\') {
char nextChar = input[i 1];
switch (nextChar) {
case '\"': result.push_back('\"'); break;
case '/': result.push_back('/'); break;
case '\\': result.push_back('\\'); break;
case 'b': result.push_back('\b'); break;
case 'f': result.push_back('\f'); break;
case 'r': result.push_back('\r'); break;
case 'n': result.push_back('\n'); break;
case 't': result.push_back('\t'); break;
default: break;
}
i ;
}
else {
result.push_back(currentChar);
}
}
return result;
}
const int32_t TREE_NODE_BOUNDNARY = INT_MIN 1; // replace null
//note:Vec() is to hanlde `vector<int>` such as `[1,2,3,4,5]`
//I put it here just for the completeness of the code, you can ignore it
template<typename T>
std::vector<T> Vec(const std::string inputStr)
{
std::vector<T> ret;
const std::string pattern = R"(([ |-]?\w*\.?[\w |#|(|)|\.]),?)";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
std::stringstream ss;
std::string treeNull = match.str(1) == "null" ? std::to_string(TREE_NODE_BOUNDNARY) : match.str(1);
ss << treeNull;
T temp;
ss >> temp;
ret.push_back(temp);
log = match.suffix();
}
if (ret.empty())
std::cout << "Failed to construct Matrix" << std::endl;
return ret;
}
template<typename T>
std::vector<std::vector<T>> Vec2(const std::string inputStr)
{
std::vector<std::vector<T>> ret;
const std::string pattern = R"((\[[^\[\]]*\]))";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
std::string vec = match.str(1);
if (is_same_v<T, string>)
{
string temp = stringToVecStr(vec);
ret.push_back(temp);
}
else {
ret.push_back(Vec<T>(vec));
}
log = match.suffix();
}
if (ret.empty()) {
std::cout << "Failed to construct Matrix" << std::endl;
}
return ret;
}
int main()
{
std::string in1 = "[\">>v\",\"v^<\",\"<><\"]";
auto t1 = stringToVecStr(in1);
cout << t1;
//cout << endl;
std::string in2 = "[[\">>v\",\"v^<\",\"<><\"],[\">>v\",\"v^<\",\"<><\"]]";
auto t2 = Vec2<string>(in2);
for (auto i : t1)cout << i << " ";
return 0;
}
It says It looks like your post is mostly code; please add some more details.
, but I really don't have anything to add.
Below is the full output:
1>------ Build started: Project: temp, Configuration: Debug x64 ------
1>Source.cpp
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(69,5): warning C4984: 'if constexpr' is a C 17 language extension
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,10): error C2665: 'std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>>::push_back': no overloaded function could convert all the argument types
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\include\vector(939,23): message : could be 'void std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>>::push_back(_Ty &&)'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,10): message : 'void std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>>::push_back(_Ty &&)': cannot convert argument 1 from 'std::string' to '_Ty &&'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,21): message : Reason: cannot convert from 'std::string' to '_Ty'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,21): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\include\vector(935,23): message : or 'void std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>>::push_back(const _Ty &)'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,10): message : 'void std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>>::push_back(const _Ty &)': cannot convert argument 1 from 'std::string' to 'const _Ty &'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,21): message : Reason: cannot convert from 'std::string' to 'const _Ty'
1> with
1> [
1> _Ty=std::vector<std::string,std::allocator<std::string>>
1> ]
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,21): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(72,10): message : while trying to match the argument list '(std::string)'
1>C:\Users\mingy\source\repos\temp\temp\Source.cpp(94,29): message : see reference to function template instantiation 'std::vector<std::vector<std::string,std::allocator<std::string>>,std::allocator<std::vector<std::string,std::allocator<std::string>>>> Vec2<std::string>(const std::string)' being compiled
1>Done building project "temp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Thanks for the discussion everyone, I think I have achieved my intent correctly
#include<iostream>
#include<string>
#include<type_traits>
#include<fstream>
#include<vector>
#include<regex>
#include<sstream>
using namespace std;
inline vector<string> VecStr(const string input) {
if (input.size() < 2) {
std::cout << "Construct vector<string> failed" << std::endl;
return{};
}
vector<string> res;
string result;
for (int i = 1; i < input.length() - 1; i ) {
char currentChar = input[i];
if (input[i] == '\\') {
char nextChar = input[i 1];
switch (nextChar) {
case '\"': result.push_back('\"'); break;
case '/': result.push_back('/'); break;
case '\\': result.push_back('\\'); break;
case 'b': result.push_back('\b'); break;
case 'f': result.push_back('\f'); break;
case 'r': result.push_back('\r'); break;
case 'n': result.push_back('\n'); break;
case 't': result.push_back('\t'); break;
default: break;
}
i ;
}
else {
result.push_back(currentChar);
}
if (input[i] == ',')
{
result.pop_back();
result.pop_back();
res.push_back(result.substr(1));
result = "";
}
}
if(!result.empty()){
result.pop_back();
res.push_back(result.substr(1));
}
return res;
}
const int32_t TREE_NODE_BOUNDNARY = INT_MIN 1; // replace null
inline std::vector<std::vector<string>> Vec2Str(const std::string inputStr)
{
std::vector<std::vector<string>> ret;
const std::string pattern = R"((\[[^\[\]]*\]))";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
const std::string vec = match.str(1);
ret.push_back(VecStr(vec));
log = match.suffix();
}
if (ret.empty()) std::cout << "Construct vector<vector<string>> failed" << std::endl;
return ret;
}
//template for int and long long
template<typename T>
std::vector<T> Vec(const std::string inputStr)
{
std::vector<T> ret;
const std::string pattern = R"(([ |-]?\w*\.?[\w |#|(|)|\.]),?)";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
std::stringstream ss;
std::string treeNull = match.str(1) == "null" ? std::to_string(TREE_NODE_BOUNDNARY) : match.str(1);
ss << treeNull;
T temp;
ss >> temp;
ret.push_back(temp);
log = match.suffix();
}
if (ret.empty())
std::cout << "Construct Vector failed" << std::endl;
return ret;
}
template<typename T>
std::vector<std::vector<int>> Vec2(const std::string inputStr)
{
std::vector<std::vector<T>> ret;
const std::string pattern = R"((\[[^\[\]]*\]))";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
const std::string vec = match.str(1);
ret.push_back(Vec<int>(vec));
log = match.suffix();
}
if (ret.empty()) std::cout << "Construct failed" << std::endl;
return ret;
}
int main()
{
std::string in1 = "[\">>v\",\"v^<\",\"<><\"]";
auto t1 = VecStr(in1);
for (auto i : t1) cout << i << endl;
std::string in2 = "[[\">>v\",\"v^<\",\"<><\"],[\">>v\",\"v^<\",\"<><\"]]";
auto t2 = Vec2Str(in2);
for (auto i : t2)for(auto j:i)cout << j << endl;
return 0;
}
CodePudding user response:
I just eliminated the compile-break , but actual situation changes are depend on your opinion and condition , So you should replace correct change.
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
using namespace std;
inline string stringToVecStr(const string input) {
string result;
for (int i = 1; i < input.length() - 1; i ) {
char currentChar = input[i];
if (input[i] == '\\') {
char nextChar = input[i 1];
switch (nextChar) {
case '\"':
result.push_back('\"');
break;
case '/':
result.push_back('/');
break;
case '\\':
result.push_back('\\');
break;
case 'b':
result.push_back('\b');
break;
case 'f':
result.push_back('\f');
break;
case 'r':
result.push_back('\r');
break;
case 'n':
result.push_back('\n');
break;
case 't':
result.push_back('\t');
break;
default:
break;
}
i ;
} else {
result.push_back(currentChar);
}
}
return result;
}
const int32_t TREE_NODE_BOUNDNARY = INT_MIN 1; // replace null
// note:Vec() is to hanlde `vector<int>` such as `[1,2,3,4,5]`
template <typename T>
std::vector<T> Vec(const std::string inputStr) {
std::vector<T> ret;
const std::string pattern = R"(([ |-]?\w*\.?[\w |#|(|)|\.]),?)";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
std::stringstream ss;
std::string treeNull = match.str(1) == "null"
? std::to_string(TREE_NODE_BOUNDNARY)
: match.str(1);
ss << treeNull;
T temp;
ss >> temp;
ret.push_back(temp);
log = match.suffix();
}
if (ret.empty()) std::cout << "构造Vector失败" << std::endl;
return ret;
}
template <typename T>
std::vector<std::vector<T>> Vec2(
const std::string &inputStr) { // change to refrence(prevent copy)
std::vector<std::vector<T>> ret;
const std::string pattern = R"((\[[^\[\]]*\]))";
std::smatch match;
std::string log = inputStr;
while (regex_search(log, match, (std::regex)pattern)) {
std::string vec = match.str(1);
if (is_same_v<T, string>) {
string temp = stringToVecStr(vec);
ret.push_back(std::vector<T>(
1, temp)); // changed -> std::vector init , but this code
// always add one string to vector if you want add
// to an item in outer vector , you should have an
// condition to add which one element?
} else {
ret.push_back(Vec<T>(vec)); // you checked type not be string , but input
// argument in Vec(...) is string . why?
}
log = match.suffix();
}
if (ret.empty()) {
std::cout << "Failed to construct Matrix" << std::endl;
}
return ret;
}
int main() {
std::string in1 = "[\">>v\",\"v^<\",\"<><\"]";
auto t1 = stringToVecStr(in1);
for (auto i : t1) cout << i;
cout << endl;
std::string in2 = "[[\">>v\",\"v^<\",\"<><\"],[\">>v\",\"v^<\",\"<><\"]]";
auto t2 = Vec2<string>(in2);
for (auto const &i : t2) // changed
for (auto const &j : i) cout << j << " ";
return 0;
}