C2784 using a set of iterators over map - templates

the code below produces compiler 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::_Tree_iterator<_Mytree>'
What is wrong with the code? Many thanks in advance; I couldn't find any posts on that error message that would help me.
#include <map>
#include <set>
void main(){
int i=1;
std::map<int, int> A;
A[i]=i;
std::set<std::map<int, int>::iterator > setOfIts;
setOfIts.insert(A.begin());
}

What you're seeing is Visual Studio's long way of complaining it has no way to compare the iterators you'd like to place in the set, because there's no appropriate operator <. And since it can't compare them, it can't decide whether two iterators have the same value, hence only one of them should be in the set.
To fix the problem, you can provide a less then operator of your own - see example here. What would be the meaning of iterators equality is up to you to figure out...

Related

Errors 2676 and 2784 (...could not deduce template argument for...) when inserting vector of structs into set

I am getting the following build errors when I try to run my program (in VS):
Error 10 error C2676: binary '<' : 'const move' does not define this operator or a conversion to a type acceptable to the predefined operator
Error 4 error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const move'
Error 8 error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const move'
Error 1 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 move'
Error 3 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const move'
Error 5 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const move'
Error 6 error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const move'
Error 9 error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const move'
Error 7 error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const move'
Error 2 error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const move'
I have no idea why they are occurring, as I haven't defined any operators in my move struct (see below), nor are there any operators in the part of my code that causes it.
They seem to be caused by this function (which is never called):
std::set<solution> solve(grid board, solution prev) {
std::set<solution> ret = {};
ret.insert(prev);
return ret;
}
My typedefs/structs that are used above:
struct move {
public:
move(unsigned startX, unsigned startY, unsigned endX, unsigned endY) {
x0 = startX;
y0 = startY;
x1 = endX;
y1 = endY;
}
unsigned x0 : 4, y0 : 4, x1 : 4, y1 : 4;
};
typedef std::vector<std::vector<__int8>> grid;
typedef std::pair<__int8, __int8> point;
typedef std::vector<move> solution;
Can anyone tell me why this is happening, and what I can do to fix it?
Thanks in advance!
There are two more things in Steephen's answer that just don't fit. The first is mostly formal, std::set uses std::less by default, not operator<. This only matters in cornercases though, because std::less uses operator< by default. There is a different issue though, and that merits a different answer, because I can't format code properly in a comment.
When passing a custom comparator to std::set as second template parameter, you must make sure that it defines a strict-weak ordering. That means that the comparator cmp must satisfy certain requirements. In particular cmp(a, a) = false and cmp(a, b) -> not cmp(b, a), which is used by the set (but also e.g. std::map) to determine equality. If cmp(a, b) = false and cmp(b, a) = false ("neither is less than the other"), it will treat the two values as equal.
Concerning the vector that you have, one suggestion was to use the euclidean distance. The euclidean distance between (3, 0) and (0, 4) is 5, as is that between (0, 3) and (4, 0), (0, 0) and (-5, 0) and infinitely many others. That means that different vectors would be considered equal, which is probably not what you wanted.
As a rule of thumb, a lexicographical sorting is a good default. In order to implement that, you simply split the operands into tuples so that each tuple value can be compared numerically. The implementation then looks like this:
bool compare_move(move const& m1, move const& m2)
{
if (m1.x0 != m2.x0) return m1.x0 < m2.x0;
if (m1.y0 != m2.y0) return m1.y0 < m2.y0;
if (m1.x1 != m2.x1) return m1.x1 < m2.x1;
return m1.y1 < m2.y1;
}
This also has the advantage that it doesn't use floating-point math. It could be improved a bit using the fact that you have bitfields with just 4 bit, so every move only occupies 16 bit of data. If you combine those to a single integer value by shifting and OR'ing them, you would get the same, but I'm not sure if that microoptimization is even worth it.
std::set creates a binary tree internally using comparison operator < by default, that is the reason you got the error specified in your question. So std::set has to keep an order internally for all its elements. So each time we insert, it will check new elements order among existing elements using comparison operator and position it accordingly.
You have to define operator < as follows inside struct move before doing insertion to std::set. I hope you can compare using http://en.wikipedia.org/wiki/Euclidean_distance
bool move::operator <(struct move & rhs)
{
return ( sqrt( (this->x1-this->x0)* (this->x1-this->x0) +
(this->y1-this->y0) * (this->y1-this->y0) ) <
sqrt( (rhs.x1-rhs.x0)* (rhs.x1-rhs.x0) +
(rhs.y1-rhs.y0) * (rhs.y1-rhs.y0) ) );
}
If you prefer to keep a custom comparison in place of <, you can do it as follows. Define your comparison operator 'customcompare` and define std::set as follows:
std::set<std::vector<move>,customcompare> ret;

error C2784 ,class in key map

I have a problem with the container map. I need to store my own class Person in key but i have error C2784 (i.e., "The compiler cannot determine a template argument from the supplied function arguments."). It's example from the book "Ivor Horton's beginning Visual C++ 2010"
#include<map>
#include<string>
#include <iostream>
using namespace std;
void main()
{
class Person{
public:
string c_name,c_surname;
Person(string name,string surname){
c_name=name;
c_surname=surname;
}
};
map<Person,string> phonebook;
phonebook.insert(make_pair(Person("Mel","GIBSON"),"24 32 23"));
phonebook[Person("Mel2","Gibson2")]="243 32 23";
/* it doesn`t work too
typedef pair<Person,string> Entry;
Entry entry1= Entry(Person("Jack","Jones"),"213 567 1234");
phonebook.insert(entry1);*/
system("Pause");
}
Error 1 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 2 error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 3 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 4 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 main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 5 error C2784: 'bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,const std::unique_ptr<_Ty2,_Dx2> &)' : could not deduce template argument for 'const std::unique_ptr<_Ty,_Dx> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 6 error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 7 error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 8 error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const main::Person' e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
Error 9 error C2676: binary '<' : 'const main::Person' does not define this operator or a conversion to a type acceptable to the predefined operator e:\microsoft visual studio 10.0\vc\include\xfunctional 125 1 AllClasses
The problem here is that std::map requires your keys to be comparable with the < operator. Custom structures/classes are not that by default, you need to make a custom operator< for comparison.
In C++03 you could not use local classes (classes defined within functions) as template arguments.
In C++11 you can.
So one fix is to update the compiler (there is Visual C++ 2013), and another fix is to move the class definition out of main.
By the way, void main is invalid as standard C++, and as standard C, and it's more to type than standard int main. If your book has void main, then that's a very ungood book. Microsoft's examples that include void main are also very ungood.
Also, by the way, the
system("Pause");
at the end is also very ungood practice because
it is not necessary, has no advantage, but
it makes the program more difficult to use and has some other problems, and to top it all,
it's Windows-specific, non-portable code.
To run a console program so that it stops at the end
in Visual Studio use Ctrl+F5, or
in Visual Studio place a breakpoint at the end of main (just click in the left margin) and run it with debugging (e.g. via keypress F5), or
run it from a command interpreter.
UPDATE: the now added error messages (even the first one) mention operator<. You need to define that also. That is, define an operator< function for your class Person.

std::map with an object as value

I have an error while trying to use std::map with my own class as value. The definition of the map is this:
std::map<std::string,CCrossSection> Xsects;
This line compiles fine (so it kindo of works?)
Xsects[sectionId].m_vProfile.push_back(pt);
When I try to iterate over the map however:
for (std::map<std::string,CCrossSection>::iterator xs = Xsects.begin(); xs < Xsects.end(); xs++) {
it->second.SaveFile(f);
}
It gives me multiple errors similar to this:
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'std::_Tree<_Traits>::iterator'
with
[
_Traits=std::_Tmap_traits<std::string,CCrossSection,std::less<std::string>,std::allocator<std::pair<const std::string,CCrossSection>>,false>
]
c:\program files\microsoft visual studio 9.0\vc\include\xtree(1466) : see declaration of 'std::operator <'
I thought that it is a problem with less operator and I added it to my definition of the class CCrossSection, but it didn't change a thing. Later I read that the key of the map has to have less operator defined and I think std::string has. Any ideas why it happens?
Cheers
Tomek
it will compile when you compare the end iterator with operator!=

std::find on std::vector< std::string > does not compile in Visual C++ 2008?

I tried this code on Visual C++ 2008 express edition, but it does not compile:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
typedef std::string Element;
typedef std::vector< Element > Vector;
typedef Vector::iterator Iterator;
Vector v;
std::find( v.begin(), v.end(), std::string( "xxx" ) );
return 0;
}
I get the following error:
c:\programmi\microsoft visual studio 9.0\vc\include\algorithm(40) : error C2784: 'bool std::operator ==(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'std::basic_string<_Elem,_Traits,_Ax>'
The same code is corrected compiled by gcc and works as expected.
Is it a bug of Visual Studio? And how can I get my example working on Visual C++ 2008?
You forgot to #include <string>.
You must always include all the headers that you need for your code. Never depend on magic recursive inclusions that happen to work sometimes. For everything you use in your code you must know where it has been declared and guarantee that the declarations are visible in your translation unit.

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