Using an std::string as a key for an std::map - c++

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.

Related

how to deal with a c++ related warning in boost option header file?

i have Microsoft Visual Studio (MSVS) 2012 Pro and i have set warning level to a slightly elevated level of 4. when doing this i am getting warnings for some of the included header files from the boost library. the message is this:
C:\Users\****\boost/optional/optional.hpp(595): warning C4244: 'initializing' : conversion from 'T_DOUBLE' to 'float', possible loss of data
C:\Users\****\boost/optional/optional.hpp(430) : see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::construct<double>(Expr &&,const void *)' being compiled
with
[
T=T_FLOAT,
Expr=T_DOUBLE
]
C:\Users\****\boost/optional/optional.hpp(430) : see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::construct<double>(Expr &&,const void *)' being compiled
with
[
T=T_FLOAT,
Expr=T_DOUBLE
]
the code in the file leading to this warning is this (line 610 on most recent beta of boost 1.64.0.B2 still resembles it exactly - but i am not on the beta now):
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
template<class Expr>
void construct ( Expr&& expr, void const* )
{
new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
m_initialized = true ;
}
what is the reason (=learn to understand) for this warning and how to eliminate it in the boost header for me any anyone else? alternatively thinking: does it make sense to "fix" it in such a global way, or is there a deeper meaning pointing rather to somewhere else (either boost or application codes) to improve or fix those other codes?
You are probably passing a double literal into method that expects float. Something like foo(1.0) instead of foo(1.0f)

C++ Debugging no '=' operator found in Visual Studio

Visual Studio gives me this error when I try to compile my C++ project:
Severity: Error
Code: C2678
Description: binary '=': no operator found which takes a left-hand operand of type 'const std::string' (or there is no acceptable conversion)
Project: jr
File: c:\program files (x86)\microsoft visual studio 14.0\vc\include\utility
Line: 192
I suppose, somewhere in my project, I'm trying to change constant string.
How do I locate this? How to go about debugging such errors?
The filename and line mentioned in the error are some read-only files by Microsoft. I'd like to locate the error in my code. Here's the excerpt of code around line 192:
_Myt& operator=(const _Myt& _Right)
{ // assign from copied pair
first = _Right.first;
second = _Right.second;
return (*this);
}
You probably want to write code like:
const std::string s;
s = "";
this is why error is saying about const type : 'const std::string'
Other possibility is that you want to assign a value to a string in a const method.

Template deduction error

Note: pls don't be confused with other Stackoverflow questions that have the same title/errocode -- they are mostly due to missing #include <string> but it's not the issue here.
I'm reading Pretty-print C++ STL containers question and downloaed Kerrek's code from his GitHub Project cxx-prettyprint, when I try compile it (my environment is Windows 7, Visual Studio 2013, compiled project as a Console Application "Use Multi-Byte Character Set"), hit a template deduction error.
It's a bit weird as suggested by Mike Kinghan in the comment, it does compile compiles and runs fine with the current MSVC++ : see it online.
I'm confused, there must be something wrong with my configuration. I created a blank new Windows Console Application, and added Kerrek's code in, focus on a vector of string test cast, removed other scenarios such as set/map etc:
int main(int argc, char* argv[])
{
std::vector<std::string> v;
v.push_back("hello, world");
v.push_back("2nd line");
v.push_back("last line");
std::cout << v;
}
, now hit a error:
Error 1 error C2679: binary '<<' : no operator found which takes a
right-hand operand of type
'std::vector>' (or there is no
acceptable conversion)
If I explicitly call the pretty_print::operator <<,
pretty_print::operator<<(std::cout, v);
, hit another template deduction error:
Error 1 error C2784: 'std::basic_ostream<_Elem,_Traits>
&pretty_print::operator <<(std::basic_ostream<_Elem,_Traits> &,const
pretty_print::print_container_helper
&)' : could not deduce template argument for 'const
pretty_print::print_container_helper
&' from 'std::vector>'
It only compiles if the print_container_helper is explictily created:
pretty_print::print_container_helper<std::vector<std::string>, char, ::std::char_traits<char>, pretty_print::delimiters<std::vector<std::string>, char>>
vh(v);
pretty_print::operator<<(std::cout, vh);
The full code is here: http://rextester.com/RJX76690

How to put std::set into std::map

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>.

member hook implementation for splay_multiset in Boost::Intrusive

I was implementing boost::intrusive for one of my project on visual C++ 2008 and i stumbled upon a problem. i am using splay hooks for splay_multiset containers. I have defined splay hook publically under MyClass (code below).
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <iostream>
using namespace boost::intrusive;
class MyClass
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
splay_set_member_hook<link_mode<normal_link> > memberSplayHook;
//**OPTION-1**
//PROBLEM CODE SEGMENT ++
//typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
//typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//PROBLEM CODE SEGMENT --
MemberMultiSet mmset;
};
//**OPTION-2**
//WORKING CODE SEGMENT ++
typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//WORKING CODE SEGMENT --
int main()
{
return 0;
}
The problem is, to use splay_multiset, whatever option i choose (either option-1 or 2, mention in code), in both cases i see compilation errors.
When Option-1 is enabled (option-2 is commented), i see errors below:
1>d:\projects\sampleproject\sample.cpp(21) : error C2327: 'MyClass::memberSplayHook' : is not a type name, static, or enumerator
1>d:\projects\sampleproject\sample.cpp(21) : error C2065: 'memberSplayHook' : undeclared identifier
1>d:\projects\sampleproject\sample.cpp(22) : error C3203: 'member_hook' : unspecialized class template can't be used as a template argument for template parameter 'O1', expected a real type
While, when Option-2 is enabled (option-1 is commented out), i dont see undeclared identifier error msg as these errors coming with option-1. But i do see errors like below (which are obvious).
1>d:\projects\sampleproject\sample.cpp(25) : error C2146: syntax error : missing ';' before identifier 'mmset'
1>d:\projects\sampleproject\sample.cpp(25) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
My question is why i am getting error in first case? What can i do to get pass this issue?
Boost member hooks have (always?) been broken, since they don't compile with Visual C++.
I don't have a VS at hand to check for the precise error message so I might be wrong (but reading 'member hooks' and 'Visual C++' always triggers 'there's a problem'-mode), but do try to check this:
http://permalink.gmane.org/gmane.comp.lib.boost.user/56875
EDIT: Don't take the headline literally -- the same applies to Visual C++ 2010 and 2012. All my member hooks use this workaround; at some point I might even try to understand what it does, or more importantly, how to package it into a more comfortable setup for less "I need to find a previous implementation of this workaround so I can copy-and-modify it"...