Thread: map with char[30] as key

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    269

    map with char[30] as key

    Hi, I'm trying to just create a map of with char[30] as the key, and type test as the value.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <map>
    #include <string.h>
    
    int main()
    {
      struct test
      {
        int number;
        char name[30];
      };
      typedef struct test test;
    
      std::map <char[30], test*> buckets;
      return 0;
    }
    However, when compiling, I get the error:

    Code:
    stupid.c: In function ‘int main()’:
    stupid.c:23: error: template argument for ‘template<class _T1, class _T2> struct std::pair’ uses local type ‘main()::test’
    stupid.c:23: error:   trying to instantiate ‘template<class _T1, class _T2> struct std::pair’
    stupid.c:23: error: template argument 4 is invalid
    stupid.c:23: error: invalid type in declaration before ‘;’ token
    What am I missing?
    Last edited by dayalsoap; 07-27-2012 at 04:10 PM.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    269
    Okay, moving my struct definition outside of the main method lets it compile. Strange. Stupid.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Roughly speaking, templates cannot be instantiated using types that are local to a function.

    The fact you are mixing C techniques with C++ techniques will make your code very error prone. Even if the compiler doesn't complain, it is a very poor idea to use an array of char as keys for a map. It's akin to the argument of having to use strcmp() function to compare strings in C, rather than the == operator.

    So I suggest looking up and using the std::string class (which is in the C++ header named <string>, not <string.h>) as the key for your map. And eliminate the usage of headers <stdio.h>, <stdlib.h>, and <string.h>.

    I'm not suggesting C techniques are bad. However, they generally do not play well with techniques used in C++.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    269
    The reason is just because it's a networked system, and the code that's sending messages to it is standard C using char [30]... I suppose I could convert between the two.. when something comes in, just go from char[30] --> string, and then I send it out, go from string --> char[30]?

    Thanks!

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    It is not hard to convert an array of char to a std::string and back. std::string has operations and functions specifically for that purpose.

    You need to make a distinction between the protocol used to communicate over the network and the implementation of applications that use that protocol. The fact that one application is written in C does not limit the other application to using C techniques. One of the most common primary reasons of breaking a system into distributed components is to allow those components to be implemented differently, without breaking each other.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Even if you are using networking C code (and you don't need to; there are C++ alternatives for networking), you should limit C to only where it is necessary. Abstract it.
    Wherever possible, you should be using C++ to write your code, and that means using C++ objects such as string.
    Anyway, using chars in a map is a disaster waiting to happen. That is because it uses relation operators (usually <) to know where to position the objects and do lookups. What happens if you do a less than comparison on a two char arrays? You compare their addresses, which is hardly what you want.
    Not to worry, though, std::string has a constructor to build an object from a C-style string. So if you use a map with a std::string, it will implicitly convert your C-style strings into std::string objects. If you need the C-style string back, use the .c_str() method. It will give you a constant C-style string.
    If you need to modify it, create a vector and copy the string over.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Anyway, using chars in a map is a disaster waiting to happen. That is because it uses relation operators (usually <) to know where to position the objects and do lookups.
    While I agree using C-strings in a map is not the best idea, it is possible but you must use the optional third parameter to the map constructor (the comparison object). See these links: map and map constructor. This method also makes it possible to use classes, structures as the key.

    Jim

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    For classes and strcuts, it is better to overload the less than operator.
    The optional third parameter is good for when using pointers in the map.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    For classes and strcuts, it is better to overload the less than operator.
    I agree, except when the source for the class is not available, or the structure can not be modified. Using the third parameter to the map allows the comparison of any object without requiring changes to that object.

    Jim

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by jimblumberg
    I agree, except when the source for the class is not available, or the structure can not be modified.
    ... and it is otherwise not possible to overload operator< as a non-member non-friend function in the same namespace. This could be due to the lack of necessary accessors or there already being an overload that does not compare what you want to compare.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    269
    There's not really an alternative to this. It's an RDMA application built on top of Jaguar's (called Titan now) Gemini interconnect. It's an API that schedules data movement two and from compute nodes in such a way that it does not perturb the on-going (MPI.. still over Gemini) communication that the simulation is doing. There really isn't a way to avoid networking when you need to exchange data on a super computer.

    "What happens if you do a less than comparison on a two char arrays? You compare their addresses, which is hardly what you want."

    My understanding is that I can specify a comparator function for my Map instance, so it shouldn't be doing any < operator.

    "Not to worry, though, std::string has a constructor to build an object from a C-style string. So if you use a map with a std::string, it will implicitly convert your C-style strings into std::string objects. If you need the C-style string back, use the .c_str() method. It will give you a constant C-style string."

    Perfect. thank you. I think this is the most straight-forward way. It should be easy enough to convert when needed; I just pull the data from the typed Gemini event queue, cast it accordingly, and then just create a string from the char array.

    Quote Originally Posted by Elysia View Post
    Even if you are using networking C code (and you don't need to; there are C++ alternatives for networking), you should limit C to only where it is necessary. Abstract it.
    Wherever possible, you should be using C++ to write your code, and that means using C++ objects such as string.
    Anyway, using chars in a map is a disaster waiting to happen. That is because it uses relation operators (usually <) to know where to position the objects and do lookups. What happens if you do a less than comparison on a two char arrays? You compare their addresses, which is hardly what you want.
    Not to worry, though, std::string has a constructor to build an object from a C-style string. So if you use a map with a std::string, it will implicitly convert your C-style strings into std::string objects. If you need the C-style string back, use the .c_str() method. It will give you a constant C-style string.
    If you need to modify it, create a vector and copy the string over.

  12. #12
    Registered User
    Join Date
    May 2010
    Posts
    269
    Quote Originally Posted by grumpy View Post
    Roughly speaking, templates cannot be instantiated using types that are local to a function.
    Turns out that there is a way to do this. After 2003, the compile option -std=c++0x allows you to do this. Older g++ versions won't allow this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 07-24-2012, 10:41 AM
  2. undefined reference to `RunSwmmDll(char*, char*, char*)'
    By amkabaasha in forum C++ Programming
    Replies: 1
    Last Post: 10-31-2011, 12:33 PM
  3. Replies: 8
    Last Post: 12-08-2009, 02:47 AM
  4. Read File To Char Array with Null char init
    By MicroFiend in forum Windows Programming
    Replies: 1
    Last Post: 10-28-2003, 06:18 PM
  5. Assigning Const Char*s, Char*s, and Char[]s to wach other
    By Inquirer in forum Linux Programming
    Replies: 1
    Last Post: 04-29-2003, 10:52 PM