How to put std::set into std::map - c++

I declared std: map below:
std::map<std::string, std::set<unsigned char*>> FilesMap;
int InsertData(unsigned char* name)
{
// here i try to insert pair with name above and clear std::set
FilesMap.insert(std::pair<std::string, std::set<unsigned char*>>(std::string((char*)name), std::set<unsigned char*>()));
}
But I have many errors like:
Error 16 error C2676: binary '<': 'const std::string' does not define
this operator or a conversion to a type acceptable to the predefined
operator c: \program files (x86)\microsoft Visual Studio
10.0\vc\include\xfunctional
What am I doing wrong?

First of all, this horribly long line
FilesMap.insert(std::pair<std::string, std::set<unsigned char*>>(std::string((char*)name), std::set<unsigned char*>()));
can be simplified if you use std::make_pair function, which will deduce template arguments.
FilesMap.insert(std::make_pair(std::string(reinterpret_cast<char*>name)), std::set<unsigned char*>()));
Second, you could make a typedef for your set so as to simplify the above line even more
typedef std::set<unsigned char*> mySetType;
std::map<std::string, mySetType>> FilesMap;
FilesMap.insert(std::make_pair(std::string(reinterpret_cast<char*>name)), MySetType()));
And lastly, and most importantly, I believe the reason that the compiler is unable to find a suitable operator < for std::string is that you forgot to #include<string>

A requirement for using std::map, is that the key type has to have an operator < . It seems you are getting an error with regards to std::string not having this operator. Make sure you have included the string header #include <string>.

Related

error C2146: syntax error : missing ',' before identifier mType when passing a map by function

When I declare the below function:
#include <vector>
#include <map>
void setTypeByBanknote(tsBanknotes &tsBanknotes, std::map<char, std::vector<byte>> &mType);
My compiler shows the following error:
error C2146: syntax error : missing ',' before identifier mType
But if I do the following:
#include <vector>
#include <map>
typedef std::vector<byte> tvByteVector;
void setTypeByBanknote(tsBanknotes &tsBanknotes, std::map<char, tvByteVector &mType);
My compiler does not show any error and compiles correctly
Is there any way to pass this map as an argument without using typedef ?
I'm using visual 6.0 as IDE, I know it is very old. Is the problem because of the old IDE ? I do include vector and map libraries.
Thanks in advance!
std::map<char, std::vector<byte> >
^^^^
You need a space between two >s like > >. Otherwise VS 6.0, which is very old, gets confused with operator >>. It's better to update the compiler.

Why do I get a compilation error when using the emplace method for unordered_map?

#include <string>
#include <unordered_map>
using namespace std;
....
....
unordered_map<char, int> hashtable;
string str = "hello";
char lower = tolower(str[0]);
hashtable.emplace(lower, 1);
....
returns the following compilation errors:
1 error C2780: 'std::pair<_Ty1,_Ty2> std::_Hash<_Traits>::emplace(_Valty &&)' : expects 1 arguments - 2 provided
2 IntelliSense: no instance of function template "std::tr1::unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>::emplace [with _Kty=char, _Ty=int, _Hasher=std::hash<char>, _Keyeq=std::equal_to<char>, _Alloc=std::allocator<std::pair<const char, int>>]" matches the argument list
You are using an old version of Visual C++ which did not correctly support emplace. Probably Visual C++ 2010.
As the Visual C++ Team Blog once said:
As required by C++11, we've implemented
emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after()
in all containers for "arbitrary" numbers of arguments (see below).
(...)
VC10 supported emplacement from 1 argument, which was not
especially useful.
The best solution would be to upgrade to the latest version of the compiler.
Following some extensions which could fix your issue
#include <utility> // for std::pair
std::unordered_map<char, int> hashtable;
char lower = 'A';
hashtable.emplace(std::pair<char, int>(lower, 1));
If your pasted code compiles seems to be depending on the underlying compiler. Handling to emplace a std::pair works for e.g. c++11--according to the spec (e.g. cplusplus.com) your code snippet should work with c++14.

Using an array as a map key is not working with C++ 11 compiler command?

I need to use an array as the map key, but I receive compiler errors indicating that the map declaration does not name a type.
I use the code in a similar question, but the code does not compile even when I have chosen the -std=c++0x or -std=c++11 compiler commands.
The code I used is:
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
dictionary[{{1, 0, 8}}] = "hello";
The error is:
error: 'dictionary' does not name a type| error: expected
unqualified-id before ']' token| ||=== Build finished: 2 errors, 0
warnings (0 minutes, 1 seconds) ===|
I see little on this topic even when searching Google. I am using CodeBlocks as my IDE and chosen the compiler commands mentioned above.
I think the error may be because you're trying to assign to dictionary in file scope. As pointed out, variables should be initialized in global scope, i.e.:
std::map<alphabet, std::string> dictionary = { {{1,0,8}, "hello"} };
Otherwise, you should put it in block scope, i.e. in a main().
#include <array>
#include <map>
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
int main()
{
dictionary[{{1, 0, 8}}] = "hello";
}
As a side note, it seems that the braces can be elided. You do not need two sets of braces. dictionary[{1, 0, 8}] will suffice.
How you compare the arrays for the map sort?
I guess you should supply compare method like this:
struct ltarray
{
bool operator()(const alphabet& s1, const alphabet& s2) const
{
//how you compare???
return (s1<s2);
}
};
and you need to init your map template with the compare method:
std::map<alphabet, std::string, ltarray> dictionary;

Using an std::string as a key for an std::map

I would like to have an std::map (int .NET 4.0). We of course know that a map is a tree and requires an operator< that string does not define for us.
Error 24 error C2676: binary '<' : 'const std::string' does not define this operator or a conversion to a type acceptable to the predefined operator c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 125 1 FXCMMarketDataServer
So I put my google-foo to work and found this solution:
struct StringComparerForMap
{
public:
bool operator()(const std::string x, const std::string y)
{
// Add compare logic here
}
};
...
std::map<std::string, CustomObject, StringComparerForMap> myMap;
This worked fine for a while, and now I'm encountering a bug that I believe is due to this. Somewhere deep down in the STL framework it would seem that it ignores the above definition and defaults to operator<.
Is there a way in VS2010 .NET 4.0 to use a string as the key of a map?
I understand that I can take that string and write a function to hash it to an int, but where's the fun in that?
EDIT
I will try and explain this as best I can for David. When the map uses the comparer struct, it crashes in release and fails a debug assertion in debug. The assert that fails is in xtree line 1746.
Expression: invalid operator<
|Abort| |Retry| |Ignore|
That is what leads me to believe that despite giving map a comparer, it still down certain paths defaults to operator< for comparison. The line in my code that causes this is:
CustomObject o = stringObjectMap[key];
Error 24 error C2676: binary '<' : 'const std::string' does not define this operator or a conversion to a type acceptable to the predefined operator c:\program files\microsoft visual studio 10.0\vc\include\xfunctional 125 1 FXCMMarketDataServer
That's what VC spits into your face when you forgot to include <string>. That header definitely defines this operator.

C++ Map can't insert with pair

Why can't I insert as shown below?
#include <map>
struct something {
} some_object;
typedef std::map<std::string, something*> list;
typedef std::pair<std::string, something*> pair;
int main()
{
list l;
pair p("abc", &some_object); // working fine!!!
l.insert(p); // 17 errors
return 0;
}
Visual studio gives me many errors and I don't understand anything of them. The first one is:
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
I can post more but I don't want to spam here. Thanks a lot for your help.
You need to
#include <string>
I would change this line:
typedef std::pair<std::string, something*> pair;
You are relaying on an implementation detail. Are you sure this wil always be true for all future version of the library? Tightly coupling your code like that is a bad idea.
Try this:
typedef list::value_type pair;
PS. 'list' would not be my first choice for the name of a type I put in the global namespace. Either put it in your own namespace or call it 'MyList'.