The following static initializer list M fails but N suceeds, it seems I cannot figure out how to do the unordered_map initialization when a union of 3 const char * pointers is added to the init-list. I tried the . notation to access the fields of the union and the union itself to no avail.
#include <iostream>
#include <unordered_map>
#include <iterator>
struct C {
int j;
int i;
};
struct D {
int j;
char c;
};
struct E {
const char *a;
const char *b;
const char *c;
}e;
struct A {
const char *s;
union {
C c;
D d;
E e;
} u;
};
std::unordered_map<unsigned int, A> m ({
{1, {"tom",53,'o'}},
{2, {"ming",40,41}},
{3, {"peter","a","b","c"}} });
std::unordered_map<unsigned int, A> n ({
{1, {"tom",53,'o'}},
{2, {"ming",40,41}} });,
int main(void) {
for ( const auto& i : m) {
const auto& j = i.second;
if (i.first == 1)
std::cout << "key: " << i.first << " value: " << j.u.d.j << ":" << j.s << ":" << j.u.d.c << std::endl;
else if (i.first == 2)
std::cout << "key: " << i.first << " value: " << j.u.c.j << ":" << j.s << ":" << j.u.c.i << std::endl;
else if (i.first == 3)
std::cout << "key: " << i.first << " value: " << j.u.e.a << ":" << j.s << ":" << j.u.e.c << std::endl;
}
for ( const auto& i : n) {
const auto& j = i.second;
if (i.first == 1)
std::cout << "key: " << i.first << " value: " << j.u.d.j << ":" << j.s << ":" << j.u.d.c << std::endl;
else if (i.first == 2)
std::cout << "key: " << i.first << " value: " << j.u.c.j << ":" << j.s << ":" << j.u.c.i << std::endl;
}
return 0;
}
Error:
map.cpp:41:32: error: no matching function for call to ‘std::unordered_map::unordered_map()’
Related
I have following test example:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result of the code above is:
init 0x7ffed27c6450 0x56480bc1eeb0 5
value 0x7ffed27c6470 0x56480bc1eeb0 5
done 0x7ffed27c6450 0 0
Looks great:
Now, move to:
#include <iostream>
#include <vector>
void foo (std::vector<int> value) {
std::cout << "value "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
void foo2 (std::vector<int>&& rvalure_ref) {
std::cout << "rvalue_ref "
<< &rvalure_ref
<< " "
<< rvalure_ref.data()
<< " "
<< rvalure_ref.size()
<< std::endl;
}
int main() {
std::vector<int> value(5, 0);
std::cout << "init "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
foo2(std::move(value));
std::cout << "done "
<< &value
<< " "
<< value.data()
<< " "
<< value.size()
<< std::endl;
}
The result is:
init 0x7ffccc93a5c0 0x56124b3a8eb0 5
rvalue_ref 0x7ffccc93a5c0 0x56124b3a8eb0 5
done 0x7ffccc93a5c0 0x56124b3a8eb0 5
My problem is:
For the 1st case, it is perfectly called by "move semantics", and as you see, the ownership of the vector has been transfered to the function parameter. Finally, at "done", the data is null to verify the the vector at main() no longer owns the vector.
Now to explicitly claim the parameter is "rvalue reference", as case 2. As you see, actually it is like "call by (l)reference".
How can I figure out it?
Using the example for std::swap on cppreference I tried the following SWAP-template:
#include <algorithm>
#include <iostream>
namespace Ns
{
class A
{
int id{};
friend void swap(A& lhs, A& rhs)
{
std::cout << "swap(" << lhs << ", " << rhs << ")\n";
std::swap(lhs.id, rhs.id);
}
friend std::ostream& operator<< (std::ostream& os, A const& a)
{
return os << "A::id=" << a.id;
}
public:
A(int i) : id{i} { }
A(A const&) = delete;
A& operator = (A const&) = delete;
};
}
template<typename T> void SWAP(T &l, T &r)
{
try { std::swap(l, r); }
catch(...) { swap(l, r); }
}
int main()
{
std::cout << "\n======================\n";
int a = 5, b = 3;
std::cout << "before: " << a << ' ' << b << '\n';
std::swap(a,b);
std::cout << "after: " << a << ' ' << b << '\n';
std::cout << "\n=========\n";
Ns::A p{6}, q{9};
std::cout << "before: " << p << ' ' << q << '\n';
// std::swap(p, q); // error, type requirements are not satisfied
swap(p, q); // OK, ADL finds the appropriate friend `swap`
std::cout << "after: " << p << ' ' << q << '\n';
std::cout << "\n======================\n";
std::cout << "before: " << a << ' ' << b << '\n';
SWAP(a,b);
std::cout << "after: " << a << ' ' << b << '\n';
std::cout << "\n=========\n";
std::cout << "before: " << p << ' ' << q << '\n';
SWAP(p, q);
std::cout << "after: " << p << ' ' << q << '\n';
}
to handle the 'friend' swap-function in the namespace; to have just a single SWAP function to call that will handle all cases.
The compiler-error: swap was not declared in this scope
Why does calling swap() for the namespace work in main but not in the template?
and is there a way to have a generalized 'SWAP'-function to handle all such cases?
(edit)
Thanks to #rici the following change to the template works:
template<typename T> void SWAP(T &l, T &r)
{
using namespace std;
swap(l, r);
}
I would still appreciate an ELI5 for the first part of my question: what/how/why does this work ...
There are 2 problems.
Please first read the definition of 'std::swap' here.
You will read the requirements for the type.
You are using exceptions in your swap function. Remove that.
From the description, you can see that your type must be
Type requirements
T must meet the requirements of MoveAssignable and MoveConstructible.
T2 must meet the requirements of Swappable.
You defined (deleted) a constructor and assign operator. With that the compiler will not create the standard constructors/assign operators for you. Please read about the rule of 5.
Your class is no longer MoveAssignable and MoveConstructible.
Simply remove the deleted operator and constructor.
Like the below. Then it will compile.
#include <algorithm>
#include <iostream>
namespace Ns
{
class A
{
int id{};
friend void swap(A& lhs, A& rhs)
{
std::cout << "swap(" << lhs << ", " << rhs << ")\n";
std::swap(lhs.id, rhs.id);
}
friend std::ostream& operator<< (std::ostream& os, A const& a)
{
return os << "A::id=" << a.id;
}
public:
A(int i) : id{ i } { }
//A(A const&) = delete;
//A& operator = (A const&) = delete;
};
}
template<typename T>
void SWAP(T& l, T& r)
{
std::swap(l, r);
}
int main()
{
std::cout << "\n======================\n";
int a = 5, b = 3;
std::cout << "before: " << a << ' ' << b << '\n';
std::swap(a, b);
std::cout << "after: " << a << ' ' << b << '\n';
std::cout << "\n=========\n";
Ns::A p{ 6 }, q{ 9 };
std::cout << "before: " << p << ' ' << q << '\n';
// std::swap(p, q); // error, type requirements are not satisfied
swap(p, q); // OK, ADL finds the appropriate friend `swap`
std::cout << "after: " << p << ' ' << q << '\n';
std::cout << "\n======================\n";
std::cout << "before: " << a << ' ' << b << '\n';
SWAP(a, b);
std::cout << "after: " << a << ' ' << b << '\n';
std::cout << "\n=========\n";
std::cout << "before: " << p << ' ' << q << '\n';
SWAP(p, q);
std::cout << "after: " << p << ' ' << q << '\n';
}
#include <iostream>
using namespace std;
void swap(int& a, int& b)
{
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
int tmp{move(a)};
cout << "address of tmp: " << &tmp << " value of tmp: " << tmp << endl;
a = move(b);
b = move(tmp);
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
}
void swap_no_move(int& a, int& b)
{
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
int tmp{ a };
cout << "address of tmp: " << &tmp << " value of tmp: " << tmp << endl;
a = b;
b = tmp;
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
}
int main() {
int a = 10;
int b = 5;
swap(a, b);
cout << endl;
int c = 10;
int d = 5;
swap_no_move(c, d);
cin.get();
return 0;
}
I have two swap functions: swap and swap_no_move. According to what I read from the book, there should be no "copy" in function swap which means the address of tmp should be the same for tmp and an in function swap. However, the output I got shows there is no difference between these two functions, did I do something wrong?
The definition
int tmp{move(a)};
doesn't move the reference or the variable a itself. It creates a brand new variable tmp which the compiler allocates space for. Then the value of a is moved into tmp.
And since moving int values can't really be done, it's exactly the same as
int tmp = a;
is there any library or example for reading a csv file in C++ like the csv module in Python?
What I need is a function to read a csv file and put each column element of a row in a map with the header name as the key value.
I can answer myself. I wrote a CSVDict class.
#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
class CSVDict {
public:
CSVDict(std::string fileName, int headerRow) {
file = std::ifstream(fileName);
for (int i = 0; i < headerRow; i++){ readNextRow(file); }
m_header = m_data;
}
std::string const& operator[](std::size_t index) const {
return m_data[index];
}
std::string const& operator[](std::string index) const {
return m_dataMap.find(index)->second;
}
bool readNextRowMap() {
readNextRow(file);
if (!file) return false;
m_dataMap.clear();
auto it_data = m_data.begin();
for (auto it = m_header.begin(); it != m_header.end(); ++it) {
m_dataMap[*it] = *it_data;
++it_data;
}
return true;
}
private:
void readNextRow(std::istream& str) {
std::string line;
std::getline(str, line);
if (!str) return;
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while (std::getline(lineStream, cell, ';')) {
m_data.push_back(cell);
}
}
std::vector<std::string> m_data;
std::vector<std::string> m_header;
std::map<std::string, std::string> m_dataMap;
std::ifstream file;
};
int main()
{
CSVDict dict("1.csv", 2);
while (dict.readNextRowMap()) {
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
}
CSVDict dict1("1.csv", 2);
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict1.readNextRowMap();
std::cout << dict1["ipField"] << " " << dict1["mdBeamEnergy"] << " " << dict1["mdBeamCurrent"] << " " << dict1["mcoBeamSizeId"] << " " << dict1["mdGantryAngle"] << " " << dict1["miLayerNumber"] << "\n";
dict.readNextRowMap();
std::cout << dict[0] << " " << dict[1] << " " << dict[2] << " " << dict[3] << " " << dict[4] << " " << dict[5] << " " << dict[6] << "\n";
return 0;
}
Example csv file:
#VALUES;;;;;;
ipField;mdBeamEnergy;mdBeamCurrent;mcoBeamSizeId;mdGantryAngle;miLayerNumber;mbRoomSwitchingLayer
24.30815;172.152971;24.30815;4;65;1;1
24.30815;172.152971;24.30815;4;65;2;0
24.30815;172.152971;24.30815;4;65;3;0
24.30815;172.152971;24.30815;4;65;4;0
24.30815;172.152971;24.30815;4;65;5;0
24.30815;172.152971;24.30815;4;65;6;0
24.30815;172.152971;24.30815;4;65;7;0
24.30815;172.152971;24.30815;4;65;8;0
usage (see main function in example):
class constructor needs to have the csv filename and the csv header line number
every readNextRowMap gets the values of the next line in the csv file
you can address the values either by number index or by header name
downside:
csv file has to have a header line
Maybe I didn't know how to search, but it's fact that I couldn't find anyone talking about this.
I have struct that has a non-type argument that depends on a type argument.
template<
typename SpecType,
SpecType NonType >
struct Struct
//...
When SpecType is a reference to a pointer (const char *&, for example) NonType behaves as if it is the address of the actual specialized argument, and not a reference.
More surprising is that if I explicitly cast NonType to SpecType, everything works as expected!
IBM says something about conversion to pointer of arrays and functions, but I don't understand it as related to my doubt.
When I create structs that have no embedded template types (S1 and S2) the same thing does ot happen.
Of course I can change it to:
template<
typename SpecType,
SpecType &NonType >
but it won't explain what I see.
Can anyone please give a deep (or dumb, if it is my stupidness) explanation?
The following example is a bit extense, but looking at its output I think my problem will be more clear:
#include <iostream>
#include <typeinfo>
using namespace std;
void f1( const char **p )
{
cout << "---------------------------------------------" << endl;
cout << "f1( const char **p ): p = \"" << p << "\"" << endl;
}
void f1( const char *p )
{
cout << "---------------------------------------------" << endl;
cout << "f1( const char *p ): p = \"" << p << "\"" << endl;
}
void f1( const int **p )
{
cout << "---------------------------------------------" << endl;
cout << "f1( const int **p ): p = \"" << p << "\"" << endl;
}
void f1( const int *p )
{
cout << "---------------------------------------------" << endl;
cout << "f1( const int *p ): p = \"" << p << "\"" << endl;
}
template<
typename SpecType,
SpecType NonType >
struct Struct
{
void f( )
{
cout << "---------------------------------------------" << endl;
cout << "SpecType is " << typeid( SpecType ).name( ) << endl;
cout << "NonType is " << typeid( NonType ).name( ) << endl;
cout << "NonType = \"" << NonType << "\"" << endl;
cout << "( SpecType )NonType = \"" << ( SpecType )NonType << "\"" << endl;
cout << "*NonType = \"" << *NonType << "\"" << endl;
cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;
f1( NonType );
}
};
template< const char *&P >
struct S1
{
void f( )
{
cout << "---------------------------------------------" << endl;
cout << "&P = \"" << &P << "\"" << endl;
cout << "P = \"" << P << "\"" << endl;
cout << "*P = \"" << *P << "\"" << endl;
f1( P );
}
};
template< const char **P >
struct S2
{
void f( )
{
cout << "---------------------------------------------" << endl;
cout << "P = \"" << P << "\"" << endl;
cout << "*P = \"" << *P << "\"" << endl;
cout << "*P[ 0 ] = \"" << **P << "\"" << endl;
f1( P );
}
};
const char * const_pname = "name";
const int pint[] = { 42, 51 };
const int *const_pint = pint;
int main( )
{
cout << "=============================================" << endl;
cout << "const_pname = " << const_pname << endl;
cout << "#const_pname = 0x" << hex << ( unsigned long )const_pname << dec << endl;
cout << "&const_pname = 0x" << hex << ( unsigned long )&const_pname << dec << endl;
cout << "=============================================" << endl;
cout << "Struct< const char *&, const_pname > constpTtname" << endl;
Struct< const char *&, const_pname > constpTtname;
constpTtname.f( );
cout << "=============================================" << endl;
cout << "Struct< const int *&, const_pint > constpTtint" << endl;
Struct< const int *&, const_pint > constpTtint;
constpTtint.f( );
cout << "=============================================" << endl;
cout << "S1< const_pname > s1" << endl;
S1< const_pname > s1;
s1.f( );
cout << "=============================================" << endl;
cout << "S2< &const_pname > s2" << endl;
S2< &const_pname > s2;
s2.f( );
return 0;
}
The output is:
$ ./nontype_mutant
=============================================
const_pname = name
#const_pname = x401624
&const_pname = 0x601e18
=============================================
Struct< const char *&, const_pname > constpTtname
---------------------------------------------
SpecType is PKc
NonType is PKc
NonType = "$#"
( SpecType )NonType = "name"
*NonType = "name"
*NonType[ 0 ] = "n"
---------------------------------------------
f1( const char *p ): p = "$#"
=============================================
Struct< const int *&, const_pint > constpTtint
---------------------------------------------
SpecType is PKi
NonType is PKi
NonType = "0x601e20"
( SpecType )NonType = "0x4017a8"
*NonType = "0x4017a8"
*NonType[ 0 ] = "42"
---------------------------------------------
f1( const int *p ): p = "0x601e20"
=============================================
S1< const_pname > s1
---------------------------------------------
&P = "0x601e18"
P = "name"
*P = "n"
---------------------------------------------
f1( const char *p ): p = "name"
=============================================
S2< &const_pname > s2
---------------------------------------------
P = "0x601e18"
*P = "name"
*P[ 0 ] = "n"
---------------------------------------------
f1( const char **p ): p = "0x601e18"
I've tried to compile your code using three compilers and two of them have very similar behavior giving the following message (approximately):
test.cpp:44:41: error: indirection requires pointer operand ('int' invalid)
cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;
^~~~~~~~~
test.cpp:93:18: note: in instantiation of member function 'Struct<const char *&, const_pname>::f' requested here
constpTtname.f( );
^
test.cpp:44:41: error: indirection requires pointer operand ('int' invalid)
cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;
^~~~~~~~~
test.cpp:98:17: note: in instantiation of member function 'Struct<const int *&, const_pint>::f' requested here
constpTtint.f( );
^
2 errors generated.
The error message seems correct and self evident to me. This was the result of using clang. Comeau's EDG based compiler was the other one to give a message very similar to this.
g++ compiled it (I believe incorrectly) and gave an output similar to that you report.