i got some issues trying to convert my map into a set
I got a "Chanson" object with this member data :
std::map<std::string,Artiste*> m_interpretes;
Here is how i add my *Artiste to my map :
void Chanson::addArtiste(Artiste* a) throw (ExceptionArtiste, ExceptionLangueIncompatible)
{
if(a!=NULL)
{
if(a->getLangue() == this->getLangue())
{
m_interpretes.insert(pair<string, Artiste*>(a->getNom(), a));
//m_interpretes[a->getNom()] = a;
}
else
{
throw ExceptionLangueIncompatible(a,this);
}
}
}
set<Artiste*> Chanson::getArtistes() const
{
//set<Artiste*> machin;
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
}
i got this error due to this function :
Error C2664: 'std::pair<_Ty1,_Ty2> std::set<_Kty>::insert(Artiste *&&) : impossible de convertir le paramètre 1 de const std::pair<_Ty1,_Ty2> en 'Artiste *&&' c:\program files (x86)\microsoft visual studio 11.0\vc\include\set 179 1
Any idea how to fix it?
A map is an associative data structure, while a set only contains unordered collection of items, so adding a pair (key, value) is invalid for the latter and only holds for the former.
To make a set of keys from a map, you can do
std::set<Artiste*> tempSet;
std::transform(m_interpretes.cbegin(), m_interpretes.cend(),
std::inserter(tempSet, tempSet.begin()),
[](const std::pair<std::string, Artiste*>& key_value)
{ return key_value.second; });
return tempSet;
The std::set constructor you are trying to use will try to construct an element from everything the range you pass it:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
But the element type of that range is
std::pair<const std::string, Artiste*>
which is definitely not convertible to Artiste*, which is why you are getting that error about not being able to convert. You could just do it manually though:
std::set<Artiste*> s;
for (const auto& pair : m_interpretes) {
s.insert(pair.second);
}
The problem is here:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
If you have a look at the types you get from the map::begin() and map::end() functions you see that you get an iterator of std::pair<string, Artiste*>.
The problem is that the set::insert() function expects the iterators it is given to be of type Artiste*.
The simplest fix would be to create the set with a for loop, as shown in Barry's answer.
Related
I want to have a method that takes a list as a parameter but this list should have default values, here is an invalid example for what I need:
void myFunc(std::list<CString> const & myList = std::list<CString>({"Val1", "Val2", "Val3"}));
When I try to use it I get
Error C2143: syntax error: missing ')' before '{'
Micrsoft Visual Studio 2010 does not support std::initializer_list. When you do
std::list<CString>({"Val1", "Val2", "Val3"})
You attempt to initialize the std::list using it's std::initializer_list constructor. Since MSVS 2010 doesn't support that you can call it.
One thing you can do is write a function that creates and initializes a list like
std::list<CString> default_list()
{
std::list<CString> temp;
temp.push_back("Val1");
temp.push_back("Val2");
temp.push_back("Val3");
return temp;
}
And then you can use that like
void myFunc(std::list<CString> const & myList = default_list());
I get the following three errors after building a project that uses tinyXml2. The errors are shown in the attached image. The offending code can be found in tinyXml2's xtree.cs file, here:
template<class _Iter>
void insert(_Iter _First, _Iter _Last)
{ // insert [_First, _Last) one at a time
_DEBUG_RANGE(_First, _Last);
for (; _First != _Last; ++_First)
{ // insert element as lvalue
const value_type& _Val = *_First;
insert(end(), _Val);
}
}
tinyXml2_Errors
I'm using (and must continue to use) VS2010
What could cause these errors?
1) error C2675: unary '++':'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator
2) error C2100: illegal indirection
3)error C2440: 'initializing': cannot convert from 'std::string' to 'const std::pair<_Ty1,_Ty2> &'
Edit: included errors
I commented everything in the class (and header) and added code until I received the error. This failure was actually not due to tinyXml2 - it was a failure to insert a string into a map.
For anyone else who has this problem in the future, here is the offending function, which generates no squiggly red lines in Visual Studio.
map<string, string> createMap(CNintendoItem ni)
{
map<string, string> xmlNodeToValue;
//ItemName is a string constant. ni.Name is a string returned from a class
xmlNodeToValue.insert(ItemName, ni.Name);//name of the item
...//several more insertions
return xmlNodeToValue;
}
One way to fix this is to use the following method to assign a value to a new key:
xmlNodeToValue[ItemName] = ni.Name;//name of the item
I would like to initalize a vector of pairs with some hard-coded values, I tried using different solutions but I keep getting compilation error. My code looks like this:
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, file),
std::make_pair(hog2, file2),
std::make_pair(hog3, file3),
std::make_pair(hog4, file4),
std::make_pair(hog5, file5),
std::make_pair(hog6, file6),
std::make_pair(hog7, file7),
std::make_pair(hog8, file8)
};
and the error I've got is:
Error C2440 '<function-style-cast>': cannot convert from 'initializer list' to '_Mypair'
Thank you for answers.
The error is because fstreams are not copy-constructible.
I would suggest you move your ifstreams to the vector of pairs; more clarity and control.
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, std::move(file)),
std::make_pair(hog2, std::move(file2)),
std::make_pair(hog3, std::move(file3)),
std::make_pair(hog4, std::move(file4)),
std::make_pair(hog5, std::move(file5)),
std::make_pair(hog6, std::move(file6)),
std::make_pair(hog7, std::move(file7)),
std::make_pair(hog8, std::move(file8))
};
The general approach to initialize the vector of pairs is OK but the problem is that std::ifstream is not copy-constructible. Hence, you won't be able to use
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, file),
...
};
However, you should be able to use std::ifstream* in the pair:
std::vector<std::pair<cv::HOGDescriptor, std::ifstream*> > hogs_files = {
std::make_pair(hog, &file),
...
};
This piece of code was working perfectly in VS 2013 but I had to update to VS 2015 and now it throws an error.
I did read https://msdn.microsoft.com/en-us/library/s5b150wd.aspx and googled quite a bit however I still have no idea how to fix this.
I'm using eigen math library to do some 3d math stuff. Eigen's Vector3d class cannot be used as a key to containers so I created my own Vector3dLite class to get around this issue.
class Vector3dLite
{
public:
float VertX, VertY,VertZ;
Vector3dLite(Vector3d& InputVert)
{
VertX = static_cast<float>(InputVert.x());
VertY = static_cast<float>(InputVert.y());
VertZ = static_cast<float>(InputVert.z());
}
Vector3dLite(Vector3dLite& InputVert)
{
VertX = InputVert.VertX;
VertY = InputVert.VertY;
VertZ = InputVert.VertZ;
}
//more operator overloading stuff below
}
Here's where compiler throws the error
map<Vector3dLite, int> VertexIds;
int unique_vertid = 0;
VertexIds.insert(make_pair(Vector3dLite(tri.Vert1), unique_vertid)); //This line
// Vert1 is an eigen Vector3d object
//...
Here's the compiler error:
error C2664: cannot convert argument 1 from 'std::pair<Vector3dLite,int>' to 'std::pair<const _Kty,_Ty> &&'
with
[
_Kty=Vector3dLite,
_Ty=int,
_Pr=std::less<Vector3dLite>,
_Alloc=std::allocator<std::pair<const Vector3dLite,int>>
]
and
[
_Kty=Vector3dLite,
_Ty=int
]
I did try writing const before Vector3dLite object but apparently syntax is not correct.
VertexIds.insert(make_pair(const Vector3dLite(tri.Vert1), unique_vertid));
Since the value type for a map has const object as the first element (the map key), you generally can't use make_pair to construct the value, as the inferred type will not be const.
You can create a pair with explicit types:
std::pair<const Vector3dLite, int>(Vector3dLite(tri.Vert1), unique_vertid)
You can use the map's type
std::map<Vector3dLite, int>::value_type(Vector3dLite(tri.Vert1), unique_vertid)
Or you can create a named const object to use is make_pair
const Vector3dLite mapkey(tri.Vert1);
make_pair(mapkey, unique_vertid);
One other note: Your constructors should take their parameters by const &.
I am trying to store email addresses written in a file and sort them by hits in the file.
I am storing the email addresses and the number of hits in a class called emailAddress.
I am managing the members of that class in a Deque in another class called AddressManager.
The sort function I am trying to use is the sort from the algorithm library. Like this.
[emailAddress.released() returns the number of hits. addressQueue is my emailAddress Deque]
bool AddressManager::swapTest(const emailAddress& address1, const emailAddress& address2)
{
cout<<"Comparing: "<<address1.released()<<" to "<<address2.released()<<endl;
return address1.released()>address2.released();
}
void AddressManager::sortAddresses()
{
sort(addressQueue.begin(),addressQueue.end(),
swapTest);
}
When I compile I get this error:
1>c:\workspace\addressmanager.cpp(36): error C3867: 'AddressManager::swapTest': function call missing argument list; use '&AddressManager::swapTest' to create a pointer to member
1>c:\workspace\addressmanager.cpp(36): error C2780: 'void std::sort(_RanIt,_RanIt)' : expects 2 arguments - 3 provided
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(3639) : see declaration of 'std::sort'
Can I pass swapTest to sort, or does it need to be defined outside of AddressManager somehow?
Or could someone suggest a way to implement my own sort in AddressManager and not use the library version at all?
Thanks,
ANkh
Just define an
struct EmailSorter
{
bool EmailSorter::operator ()(const emailAddress &a, const emailAddress &b) {
return a.released()>b.released();
}
};
EmailSorter es;
std::sort( v.begin() , v.end() , es );
and pass it to std::sort
Or make swapTest a static function and do
std::sort( v.begin() , v.end() , &AddressManager::swapTest );
Either make swapTest a static function, or use a lambda:
sort(addressQueue.begin(),addressQueue.end(),
[](const emailAddress& address1, const emailAddress& address2)
{ return address1.released() > address2.released(); }
);