std::map<int, std::string[2]> problems

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Erik Wikström

    std::map<int, std::string[2]> problems

    First of all, forgive me if this is the wrong place to ask this question,
    if it's a stupid question (it's my second week with C++), or if this is
    answered some place else (I've searched but not found anything).

    Here's the problem, I have two sets of files, the name of a file contains a
    number which is unique for each set but it's possible (even probable) that
    two files in different sets have the same numbers. I want to store these
    file-names in such a way that I can retrieve them by their number. For this
    I thought I'd use a map with the number as the key an an array of strings
    to store the file-names, however I've run into trouble when trying to use
    this solution.

    When adding the file-names to the map I don't know if a filename from the
    other set already exists, but given examples at:


    it seams like entries not found are created and if they are found I can
    modify them.


    Here's code that displays my problem:

    #include <map>
    #include <string>
    #include <vector>

    using std::map;
    using std::string;
    using std::vector;

    class Files
    {
    public:
    void nextFile(string *, string*);
    void open(vector<str ing>*, int);

    private:
    int getNumber(strin g); // Gets the number from the filename

    map<int, string[2]> fileSets;
    map<int, string[2]>::iterator iter;
    };

    // Return the next pair of files
    // I've removed a bit of code to keep it short,
    // among other things checks for fileSets.end().
    void Files::nextFile (string* file1, string* file2)
    {
    iter++;
    // Return the pointers to the filenames
    file1 = &(iter->second[0]);
    file2 = &(iter->second[1]);
    }


    // Add files to the sets
    // files is a vector with the filenames to be added.
    // setNr is the number of the set the files should be
    // added to, can be 0 or 1.
    void Files::open(vec tor<string>* files, int setNr)
    {
    if(setNr < 2)
    {
    for(int i = 0; i < files->size(); i++)
    {
    // Add the file to the correct set
    int fileNumber = getNumber((*fil es)[i]);
    (fileSets[fileNumber])[setNr] = (*files)[i];
    // This does not work ^^^^^^^
    }
    }

    // Set the iterator
    iter = fileSets.begin( );
    }

    ------------------------------------------

    When compiling on gcc 3.3 I get the following:

    /usr/include/c++/3.3.4/bits/stl_map.h: In member function `_Tp& std::map<_Key,
    _Tp, _Compare, _Alloc>::operat or[](const _Key&) [with _Key = int, _Tp =
    std::string[2], _Compare = std::less<int>, _Alloc =
    std::allocator< std::pair<const int, std::string[2]> >]':
    Files.cpp:46: instantiated from here
    /usr/include/c++/3.3.4/bits/stl_map.h:319: error: ISO C++ forbids casting to an
    array type `std::string[2]'

    ------------------------------------------
    and I get similar results when using gcc 3.4. Obviously there's some problem
    with the array but I can't figure out what and would appreciate a nudge in the
    right direction, and since I'm still learning any other comment too.

    PS:
    It's not possible to get random access to a map if the key is not known
    but if I have an (bidirectional) iterator pointing at some element in the
    map, and know that the element I'm interested in is N elements from the one
    the iterator is currently pointing at can I jump to that element by adding
    N to the iterator, e.g. iter+=N ?

    --
    Erik Wikström
  • Victor Bazarov

    #2
    Re: std::map&lt;int , std::string[2]&gt; problems

    Erik Wikström wrote:[color=blue]
    > First of all, forgive me if this is the wrong place to ask this question,[/color]

    It's not. You're fine.
    [color=blue]
    > if it's a stupid question (it's my second week with C++), or if this is
    > answered some place else (I've searched but not found anything).[/color]

    It may have been answered already, but sometimes it's rather hard to find.
    [color=blue]
    > [...]
    >
    > map<int, string[2]> fileSets;[/color]

    You simply can't do that. Arrays cannot be the stored data in a standard
    container. If you need two strings there, either make a pair (std::pair)
    or make your own struct.
    [color=blue]
    > [...][/color]

    V

    Comment

    • Heinz Ozwirk

      #3
      Re: std::map&lt;int , std::string[2]&gt; problems


      "Erik Wikström" <erik-wikstrom@telia. com> schrieb im Newsbeitrag
      news:XOkre.2719 7$d5.178973@new sb.telia.net...[color=blue]
      > Here's the problem, I have two sets of files, the name of a file contains
      > a
      > number which is unique for each set but it's possible (even probable) that
      > two files in different sets have the same numbers. I want to store these
      > file-names in such a way that I can retrieve them by their number. For
      > this
      > I thought I'd use a map with the number as the key an an array of strings
      > to store the file-names, however I've run into trouble when trying to use
      > this solution.[/color]

      As Victor already explained, you cannot use a C style array as the value
      type of a standard container. But you could use an std:: vector instead.
      However, as you describe your problem, you have two sets of files, not one
      set of pairs of files. So I would suggest to use two instances of
      std::map<int, std::string>, one for each set of files.
      [color=blue]
      > PS:
      > It's not possible to get random access to a map if the key is not known
      > but if I have an (bidirectional) iterator pointing at some element in the
      > map, and know that the element I'm interested in is N elements from the
      > one
      > the iterator is currently pointing at can I jump to that element by adding
      > N to the iterator, e.g. iter+=N ?[/color]

      Have a look at std::advance.

      HTH
      Heinz


      Comment

      • Gernot Frisch

        #4
        Re: std::map&lt;int , std::string[2]&gt; problems

        > map<int, string[2]> fileSets;

        string[2] has no = operator and no < operator - that's the whole
        problem.
        -Gernot


        Comment

        • Robbie Hatley

          #5
          Re: std::map&lt;int , std::string[2]&gt; problems

          Victor Bazarov wrote:[color=blue]
          > Erik Wikström wrote:[color=green]
          > > map<int, string[2]> fileSets;[/color]
          > You simply can't do that. Arrays cannot be the stored data
          > in a standard container. If you need two strings there,
          > either make a pair (std::pair)[/color]

          But in the case in question, the array did not constitute
          the "stored data". The "stored data" elements in the map
          are actually of type std::pair<int, std::string[2]>.
          What's wrong with that?


          --
          Cheers,
          Robbie Hatley
          Tustin, CA, USA
          email: lonewolfintj at pacbell dot net
          web: home dot pacbell dot net slant earnur slant



          ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
          http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
          ----= East and West-Coast Server Farms - Total Privacy via Encryption =----

          Comment

          • Robbie Hatley

            #6
            Re: std::map&lt;int , std::string[2]&gt; problems

            "Gernot Frisch" <Me@Privacy.net > wrote in message
            news:3h7cfhFfg3 7bU1@individual .net...[color=blue][color=green]
            > > map<int, string[2]> fileSets;[/color]
            >
            > string[2] has no = operator and no < operator - that's the whole
            > problem.
            > -Gernot[/color]

            The comparison in the original post was being done on type int,
            which DOES have "=" and "<" operators. std::map contains elements
            of type std::pair<key_t ype, value_type>. Only the key_type
            needs to be "comparable ", as i understand it.

            For example, the following program compiles fine:

            #include <iostream>
            #include <string>
            #include <map>
            #include <utility>
            using std::cout;
            using std::endl;
            using std::string;
            using std::map;
            using std::pair;
            using std::make_pair;
            int main(void)
            {
            string Splat[2] = {"apple", "peach"};
            map<int, string[2]> fileSets;
            fileSets.insert (make_pair<int, string[2]>(37, Splat));
            return 0;
            }

            However, when I try to run it, I get a general protection fault.
            What am I doing wrong? I don't think it has to do with the
            non-comparibility of std::string[2] , though. GPF usually
            means illegal memory usage somewhere. (Possibly a problem
            with the copy semantics of std::string[2]?)


            Puzzled,
            Robbie Hatley
            Tustin, CA, USA
            email: lonewolfintj at pacbell dot net
            web: home dot pacbell dot net slant earnur slant



            ----== Posted via Newsfeeds.Com - Unlimited-Uncensored-Secure Usenet News==----
            http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
            ----= East and West-Coast Server Farms - Total Privacy via Encryption =----

            Comment

            • Gernot Frisch

              #7
              Re: std::map&lt;int , std::string[2]&gt; problems


              "Robbie Hatley" <lonewolfintj at pacbell dot net> schrieb im
              Newsbeitrag news:42aec9a5$1 _2@spool9-west.superfeed. net...[color=blue]
              > "Gernot Frisch" <Me@Privacy.net > wrote in message
              > news:3h7cfhFfg3 7bU1@individual .net...[color=green][color=darkred]
              >> > map<int, string[2]> fileSets;[/color]
              >>
              >> string[2] has no = operator and no < operator - that's the whole
              >> problem.
              >> -Gernot[/color]
              >
              > The comparison in the original post was being done on type int,
              > which DOES have "=" and "<" operators. std::map contains elements
              > of type std::pair<key_t ype, value_type>. Only the key_type
              > needs to be "comparable ", as i understand it.
              >
              > For example, the following program compiles fine:
              >
              > #include <iostream>
              > #include <string>
              > #include <map>
              > #include <utility>
              > using std::cout;
              > using std::endl;
              > using std::string;
              > using std::map;
              > using std::pair;
              > using std::make_pair;
              > int main(void)
              > {
              > string Splat[2] = {"apple", "peach"};
              > map<int, string[2]> fileSets;
              > fileSets.insert (make_pair<int, string[2]>(37, Splat));
              > return 0;
              > }
              >
              > However, when I try to run it, I get a general protection fault.
              > What am I doing wrong? I don't think it has to do with the
              > non-comparibility of std::string[2] , though. GPF usually
              > means illegal memory usage somewhere. (Possibly a problem
              > with the copy semantics of std::string[2]?)
              >[/color]

              The second argument must either have an = operator or an cctor - I'm
              not sure, I think it't the = op, which string[2] does not offer.


              Comment

              • Mathias Waack

                #8
                Re: std::map&lt;int , std::string[2]&gt; problems

                Gernot Frisch wrote:
                [color=blue]
                > The second argument must either have an = operator or an cctor - I'm
                > not sure, I think it't the = op, which string[2] does not offer.[/color]

                For each STL container holds that the value type must be assignable and copy
                constructable (23.1.3).

                But why does this code compile?

                Mathias

                Comment

                • Dan Cernat

                  #9
                  Re: std::map&lt;int , std::string[2]&gt; problems

                  I suspect that string[2] decays to a pointer to its first element.

                  Dan

                  Comment

                  • Victor Bazarov

                    #10
                    Re: std::map&lt;int , std::string[2]&gt; problems

                    Dan Cernat wrote:[color=blue]
                    > I suspect that string[2] decays to a pointer to its first element.[/color]

                    Huh? Decays? Where?

                    Most likely it compiles in some situations because none of the member
                    function of the class template 'map' are used that require copying or
                    assigning of the value. As soon as you employ one of them, there will
                    be an error.

                    V

                    Comment

                    • Dan Cernat

                      #11
                      Re: std::map&lt;int , std::string[2]&gt; problems

                      Well, actually, I tried the code on VC7.1 and it doesn't compile
                      (cannot create the pair because it cannot find the appropriate copy
                      constructor for the type string[2]).
                      I was thinking that it compiles because, in the process of construction
                      of the contained element of type string[2], it converts the array into
                      a pointer to its first element and it copies the pointer, hence the GPF
                      he gets.

                      Your explanation doesn't explain the GPF he gets.

                      Dan

                      Comment

                      • Victor Bazarov

                        #12
                        Re: std::map&lt;int , std::string[2]&gt; problems

                        Dan Cernat wrote:[color=blue]
                        > [..]
                        > Your explanation doesn't explain the GPF he gets.[/color]

                        No, it doesn't. It wasn't meant to. The code is not supposed
                        to compile. For all I know, he runs some other program that
                        gives him the GPF while the code posted never actually makes it
                        to the executable stage.

                        If he needs the GPF explained, he has to go to the newsgroup for
                        the particular compiler he uses (and that's not VC+ v6 or v7.1
                        since both rightfully refuse to compile the code) and ask there.

                        V

                        Comment

                        • Ron Natalie

                          #13
                          Re: std::map&lt;int , std::string[2]&gt; problems

                          Victor Bazarov wrote:[color=blue]
                          > Dan Cernat wrote:
                          >[color=green]
                          >> [..]
                          >> Your explanation doesn't explain the GPF he gets.[/color]
                          >
                          >
                          > No, it doesn't. It wasn't meant to. The code is not supposed
                          > to compile.[/color]
                          Actually, it's undefined behavior. Speculating on whether it compiles
                          or does something useful when it runs is just silly.

                          Comment

                          • Mathias Waack

                            #14
                            Re: std::map&lt;int , std::string[2]&gt; problems

                            Victor Bazarov wrote:
                            [color=blue]
                            > No, it doesn't. It wasn't meant to. The code is not supposed
                            > to compile. For all I know, he runs some other program that
                            > gives him the GPF while the code posted never actually makes it
                            > to the executable stage.[/color]

                            The code compiles fine at least with gcc 3.3.5. And raises an exception
                            during runtime.

                            Mathias

                            Comment

                            • Gernot Frisch

                              #15
                              Re: std::map&lt;int , std::string[2]&gt; problems

                              > The code compiles fine at least with gcc 3.3.5. And raises an[color=blue]
                              > exception
                              > during runtime.[/color]

                              How 'bout gcc 3.4?


                              Comment

                              Working...