Anonymous
Anonymous

Reputation: 1550

c++: unable to instantiate std::set a template class

Given the following class

template <typename T>
class Plane
{
public:
    Plane<T>(T A, T B, T C, const Vector3<T>& vec):
        A(A),
        B(B),
        C(C),
        D(-1*A*vec.x-B*vec.y-C*vec.z)
    {

    }

    Plane<T>():
        A(0),
        B(0),
        C(0),
        D(0)
    {

    }


    bool CalculateTime(const Vector3<T>& r0,  const Vector3<T>& rd, T& result )
    {
        Vector3<T> vec(A,B,C);

        if ( vec.dot(rd))
        {
            result = -1;
            return false;
        }
        else
        {
            result = (vec.dot(r0) + D)/vec.dot(rd);
            return true;
        }
    }

    T A;
    T B;
    T C;
    T D;
};

For some strange reason when I do the following

    std::set<Plane<float> > s;
    s.insert(Plane<float>(10,20,30,Vector3f(10,30,40)));

this produced a massive error

1>          with
1>          [
1>              T=float
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xtree(2245) : see declaration of 'std::operator <'
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(179) : while compiling class template member function 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const'
1>          with
1>          [
1>              _Ty=Plane<float>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(559) : see reference to function template instantiation 'bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const' being compiled
1>          with
1>          [
1>              _Ty=Plane<float>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743) : see reference to class template instantiation 'std::less<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=Plane<float>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xtree(1028) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::less<Plane<float>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\set(44) : see reference to class template instantiation 'std::_Tree<_Traits>' being compiled
1>          with
1>          [
1>              _Traits=std::_Tset_traits<Plane<float>,std::less<Plane<float>>,std::allocator<Plane<float>>,false>
1>          ]
1>          c:\users\awesome2\google drive\university\eng 3gc3\assignment 3\voxelmodeler\voxelmodeler\voxelcube.h(44) : see reference to class template instantiation 'std::set<_Kty>' being compiled
1>          with
1>          [
1>              _Kty=Plane<float>
1>          ]
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(180): 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 Plane<T>'
1>          with
1>          [
1>              T=float
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1983) : see declaration of 'std::operator <'
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(180): 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 Plane<T>'
1>          with
1>          [
1>              T=float
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1259) : see declaration of 'std::operator <'
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(180): 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 Plane<T>'
1>          with
1>          [
1>              T=float
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(1075) : see declaration of 'std::operator <'
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(180): 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 Plane<T>'
1>          with
1>          [
1>              T=float
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\utility(232) : see declaration of 'std::operator <'
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstddef(180): error C2676: binary '<' : 'const Plane<T>' does not define this operator or a conversion to a type acceptable to the predefined operator
1>          with
1>          [
1>              T=float
1>          ]

Upvotes: 1

Views: 2298

Answers (2)

beerboy
beerboy

Reputation: 1294

The important part is at the end of your error message:

...
error C2676: binary '<' : 'const Plane<T>' does not define this operator
or a conversion to a type acceptable to the predefined operator

Elements of a std::set need to be orderable ie. it needs to be able to say one object is less than another.

The most strightforward way to do this is to implement an operator < method for your class. Unfortunately, it's not straightforward to define what 'less than' means for a 3-dimensional plane!

It might be worth investigating using std::unordered_set, which only requires elements to be comparable.

Upvotes: 4

Elvis Dukaj
Elvis Dukaj

Reputation: 7368

The set (as multiset, map and multimap) need a comparision function, or operator. When not specified set, multiset, map and multimap use the std::less functior object to ordinate elements in the set. So you have to write something like this

template <typename T>
class Plane {
public:
    friend bool operator < (const Plane<T>& p1, const Plane<T>& p2)
    {
         return ???
    }
};

As you can see is not a good a class like Plane in a set, maybe is better an unordered_set or simply a std::vector

Upvotes: 2

Related Questions