SFML community forums

Help => System => Topic started by: Xurix on August 28, 2012, 02:00:58 pm

Title: Using std::map and sf::Vector as key?
Post by: Xurix on August 28, 2012, 02:00:58 pm
Yoho all, Is it possible to use a sf::Vector*<*> as the key for a std::map? I've been trying to use it and I keep getting errors about it attempting to compare them past checking the x/y/z matches up.

The Error being " /usr/include/c++/4.6/bits/stl_function.h|236|error: no match for ‘operator<’ in ‘__x < __y’| "

Here's minimal code just to show it.
#include <SFML/System.hpp>
#include <map>

int main()
{
    std::map<sf::Vector3i,int> mymap;

    mymap[sf::Vector3i(1,1,1)] = 1;

    return 0;
}
 

Is there any solution for me or should I just use strings or something as the key instead (obviously putting the numbers together in a stringstream).
Title: Re: Using std::map and sf::Vector as key?
Post by: FRex on August 28, 2012, 02:08:44 pm
You need to create and pass a 3rd template parameter that will be a comparsion class functor because <(default if you don't pass 3rd parameter to map) is not overloaded for Vector3i.
Title: Re: Using std::map and sf::Vector as key?
Post by: Nexus on August 28, 2012, 02:08:53 pm
You need a custom comparison predicate (std::map's third template parameter), since there is no inequality relation for mathematical vectors.

Do you have a specific criterion after which you want to sort the map? Otherwise, you could first compare the X component, then Y, and at last Z. If your standard library supports std::tuple, you can delegate the comparison to it.
Title: Re: Using std::map and sf::Vector as key?
Post by: eXpl0it3r on August 28, 2012, 02:15:07 pm
Yes it's possible, since the requirements for the key type are that it must be copiable and assignable.
But since std::map is ordered it also requires a ordering function, by default (i.e. if you don't specify one) it will use operator<, which for sf::Vector3<T> is not declared (see documentation (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Vector3.php)), that's why you're getting that error.

The std::map deceleration is:
template < class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map;
For which the reference (http://www.cplusplus.com/reference/stl/map/) states:
Quote
  • Key: Type of the key values. Each element in a map is uniquely identified by its key value.
  • T: Type of the mapped value. Each element in a map is used to store some data as its mapped value.
  • Compare: Comparison class: A class that takes two arguments of the key type and returns a bool. The expression comp(a,b), where comp is an object of this comparison class and a and b are key values, shall return true if a is to be placed at an earlier position than b in a strict weak ordering operation. This can either be a class implementing a function call operator or a pointer to a function (see constructor for an example). This defaults to less<Key>, which returns the same as applying the less-than operator (a<b).
    The map object uses this expression to determine the position of the elements in the container. All elements in a map container are ordered following this rule at all times.
  • Allocator: Type of the allocator object used to define the storage allocation model. By default, the allocator class template is used, which defines the simplest memory allocation model and is value-independent.

Thus you'll have to define a compare functor to pass as third argument of the vector decelration. ;)
Title: Re: Using std::map and sf::Vector as key?
Post by: Xurix on August 28, 2012, 02:57:37 pm
Oh doh, thanks guys. I've written a functor and it works now :)