Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a struct into a map

I'm having trouble adding a struct into a map. I don't really understand the error.

There are 2 errors:

  1. I can't declare a map with 'struct' type
  2. I can't use insert to 'insert' my struct into the map

What am I doing wrong?

#include <iostream>
#include <map>

int main()
{

    typedef struct 
    {   
        std::string stringVar;
        unsigned unsignedVar;
        float floatVar;
    } MyTypeDefStruct;

    MyTypeDefStruct myTypeDefStruct;
    myTypeDefStruct.stringVar = "myStr";
    myTypeDefStruct.unsignedVar = 1000;
    myTypeDefStruct.floatVar = -10.0;

    float anotherFloat = -20.0;

    std::map<MyTypeDefStruct, float> myMap;

    myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));                                                                                                                                                                                                      

    return 0;
}

error:

test.cpp: In function 'int main()':
test.cpp:21:36: error: template argument for 'template<class _Tp> struct std::less' uses local type 'main()::MyTypeDefStruct'
 std::map<MyTypeDefStruct, float> myMap;
                                ^
test.cpp:21:36: error:   trying to instantiate 'template<class _Tp> struct std::less'
test.cpp:21:36: error: template argument 3 is invalid
test.cpp:21:36: error: template argument for 'template<class _T1, class _T2> struct std::pair' uses local type 'const main()::MyTypeDefStruct'
test.cpp:21:36: error:   trying to instantiate 'template<class _T1, class _T2> struct std::pair'
test.cpp:21:36: error: template argument 4 is invalid
test.cpp:21:43: error: invalid type in declaration before ';' token
 std::map<MyTypeDefStruct, float> myMap;
                                       ^
test.cpp:23:11: error: request for member 'insert' in 'myMap', which is of non-class type 'int'
 myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
       ^
test.cpp:23:50: error: template argument for 'template<class _T1, class _T2> struct std::pair' uses local type 'main()::MyTypeDefStruct'
 myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
                                              ^
test.cpp:23:50: error:   trying to instantiate 'template<class _T1, class _T2> struct std::pair'
like image 453
wait_wut Avatar asked Mar 28 '26 19:03

wait_wut


1 Answers

There are several issues in your code:

  1. The struct should defined outside of the function main, can't see a reason why you want to define it there in this case, and since it is local inside of main, you can't use it anywhere else!
  2. You are using the C-style typedef struct ... StructName instead of simply using struct MyStruct.
  3. Your struct doesn't implement the operator<, hence, since std::map is an ordered map, and it doesn't have anyway to compare two keys (here, the key is your struct), it doesn't able to insert any pair.
  4. Your struct doesn't implement the operator== which is important to actually retrieving the value of a certain key... You should be able to check if the keys are similar.
  5. Another small fix - using std::make_pair instead of its ctor.

Your code should look like:

#include <iostream>
#include <map>

struct MyStruct
{   
    std::string stringVar;
    unsigned unsignedVar;
    float floatVar;

    friend bool operator<(const MyStruct& l, const MyStruct& r)
    {
        return std::tie(l.stringVar, l.unsignedVar, l.floatVar)
             < std::tie(r.stringVar, r.unsignedVar, r.floatVar);
    }

    friend bool operator==(const MyStruct& l, const MyStruct& r)
    {
        return std::tie(l.stringVar, l.unsignedVar, l.floatVar)
             == std::tie(r.stringVar, r.unsignedVar, r.floatVar);
    }
};  

int main()
{
    MyStruct my_struct;
    my_struct.stringVar = "myStr";
    my_struct.unsignedVar = 1000;
    my_struct.floatVar = -10.0;

    float anotherFloat = -20.0;

    std::map<MyStruct, float> myMap;

    myMap.insert(std::make_pair(my_struct, anotherFloat));

    return 0;
}

How did I get to identifying the first problem? In the first error (always look at the first error, the others may be misleading!), it is written:

test.cpp:21:36: error: template argument for 'template<class _Tp> struct std::less' uses local type 'main()::MyTypeDefStruct'
 std::map<MyTypeDefStruct, float> myMap;

Notice that the template initialization here is using main()::MyTypeDefStruct and not MyTypeDefStruct!!! These types are different, and the first is available only in the scope of main()!

The third point is because when you fix the first point, you will get:

error: no match for 'operator<' (operand types are 'const MyStruct' and 'const MyStruct')
like image 62
Kerek Avatar answered Apr 01 '26 10:04

Kerek