#1
  1. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244

    map template problems


    I am working on an application (IP packet sniffer) and am using a map to store information. I have two structures that are used in a map that contains another map. I was able to get a version to run that was made up of strings (see below), but I want to avoid the performance hit of all that conversion and just store the raw data. Here are my structures and the map declaration:

    Code:
    struct IPDATA {
        in_addr first;
        in_addr second;
        unsigned char protocol;
    };
    
    struct PORTDATA{
    	unsigned short src;
    	unsigned short dst;
    };
    
    std::map < IPDATA, std::map < PORTDATA, unsigned long > > m_mapData;
    Here is where I fill the map with data:

    Code:
        memset(&SockAddr, 0, sizeof(SockAddr));
        SockAddr.sin_addr.s_addr = iphdr->SrcIP;
        ip.first = SockAddr.sin_addr;
    
        memset(&SockAddr, 0, sizeof(SockAddr));
        SockAddr.sin_addr.s_addr = iphdr->DstIP;
        ip.second = SockAddr.sin_addr;
    
        ip.protocol = iphdr->Protocol;
    
        portDat.src = 0;
        portDat.dst = 0;
        if (ip.protocol == 6 || ip.protocol == 17){// TCP or UDP
            portDat.src = port->SrcPort;
            portDat.dst = port->DstPort;
        }
        m_mapData[ip][portDat] += iphdr->Total_len;
    //if I comment out the above line, it compiles
    When I compile it (Visual C++ 6.0) I get these errors:
    ------------------------------------

    Compiling...
    Main.cpp
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::basic_string<_E,_Tr,_A> &,const _E *)' : could not deduce template argument for 'const class std::basic_string<_E,_Tr,_A> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const _E *,const class std::basic_string<_E,_Tr,_A> &)' : could not deduce template argument for 'const *' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::basic_string<_E,_Tr,_A> &,const class std::basic_string<_E,_Tr,_A> &)' : could not deduce template argument for 'const class std::basic_string<_E,_Tr,_A> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::multimap<_K,_Ty,_Pr,_A> &,const class std::multimap<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const class std::multimap<_K,_Ty,_Pr,_A> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::map<_K,_Ty,_Pr,_A> &,const class std::map<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const class std::map<_K,_Ty,_Pr,_A> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::_Tree<_K,_Ty,_Kfn,_Pr,_A> &,const class std::_Tree<_K,_Ty,_Kfn,_Pr,_A> &)' : could not deduce template argument for 'const class std::_Tree<_K,_Ty,_Kfn,_Pr,_A> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &,const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &)' : could not deduce template argument for 'const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const struct std::pair<_T1,_T2> &,const struct std::pair<_T1,_T2> &)' : could not deduce template argument for 'const struct std::pair<_T1,_T2> &' from 'const struct IPDATA'
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    c:\microsoft visual studio\vc98\include\functional(86) : error C2676: binary '<' : 'const struct IPDATA' does not define this operator or a conversion to a type acceptable to the predefined operator
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<struct IPDATA>::operator ()(const struct IPDATA &,const struct IPDATA &) const'
    Error executing cl.exe.

    Main.obj - 9 error(s), 0 warning(s)
    ------------------------------------

    This is the code the compiler is complaining about:

    Code:
    		// TEMPLATE STRUCT less
    template<class _Ty>
    	struct less : binary_function<_Ty, _Ty, bool> {
    	bool operator()(const _Ty& _X, const _Ty& _Y) const
    		{return (_X < _Y); } //<-- line 86
    	};
    I was able to get it to compile and run using strings:

    [code/

    //declare:
    std::map < std::string, std::map < std::string, unsigned long > > m_mapData;

    //use
    m_mapData[strIPs][strPorts] += iphdr->Total_len;

    [/code]

    Since the string version worked, I am at a loss on why the other version doesn't even compile. Templates are all voodoo to me, so any advice is greatly appreciated!

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    Just a wild guess, but I think you'll need to overload the < operator for IPDATA. This is because map is a sorted container object and will automatically sort anything that is inserted into it, by the key value. For the sorting operation, it needs a comparision operator. For the string type, the < operator is already overloaded, which is why it works. However, you haven't defined a < operator overload for your IPDATA type, which is why it is complaining. The following code is off the top of my head (bold lines are my additions), so you may need to make some minor mods, if it doesn't compile.

    Code:
    struct IPDATA {
        in_addr first;
        in_addr second;
        unsigned char protocol;
        bool operator< (const IPDATA& right) const;
    };
    
    bool IPDATA::operator <(const IPDATA& right) {
        // Put method of comparision here 
        if ((first < right.first)  && (second < right.second))
           return true;
        else
           return false;
    }
    
    Hope this helps :)

    [edit]You'll also need to do the same for the PORTDATA structure, because you're using that as the key in the inner map.[/edit]
    Last edited by Scorpions4ever; August 21st, 2003 at 08:23 PM.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  4. #3
  5. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244

    8 down, 1 to go!


    OK, I made these changes and got rid of 8 of the 9 errors:

    Code:
    class IPDATA {
    public:
        in_addr first;
        in_addr second;
        unsigned char protocol;
    
        bool operator <(const IPDATA& right) {
            if ((first.S_un.S_addr < right.first.S_un.S_addr)  &&
                    (second.S_un.S_addr < right.second.S_un.S_addr))
               return true;
            else
               return false;
        }
    };
    
    class PORTDATA{
    public:
        unsigned short src;
        unsigned short dst;
    
        bool operator <(const PORTDATA& right) {
            if ((src < right.src)  && (dst < right.dst))
               return true;
            else
               return false;
        }
    };
    This the error:

    -----------------------------------
    Compiling...
    Main.cpp
    c:\microsoft visual studio\vc98\include\functional(86) : error C2678: binary '<' : no operator defined which takes a left-hand operand of type 'const class IPDATA' (or there is no acceptable conversion)
    c:\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class IPDATA>::operator ()(const class IPDATA &,const class IPDATA &) const'
    Error executing cl.exe.
    Creating browse info file...

    Main.exe - 1 error(s), 0 warning(s)
    -----------------------------------

    Your explantion sounds quite reasonable and (I am ashamed a bit to say) rather obvious now, yet even with this clarity of hind sight, I still can't see what I am still missing.

    Thanks for your rapid response!

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  6. #4
  7. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244

    Got it!


    A minor change:

    Code:
    class IPDATA {
    public:
        in_addr first;
        in_addr second;
        unsigned char protocol;
    
        bool operator <(const IPDATA& right) const {//<---
            if ((first.S_un.S_addr < right.first.S_un.S_addr)  &&
                    (second.S_un.S_addr < right.second.S_un.S_addr))
               return true;
            else
               return false;
        }
    };
    
    class PORTDATA{
    public:
        unsigned short src;
        unsigned short dst;
    
        bool operator <(const PORTDATA& right) const {//<---
            if ((src < right.src)  && (dst < right.dst))
               return true;
            else
               return false;
        }
    };

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw

IMN logo majestic logo threadwatch logo seochat tools logo