Thread: Convert VisualC++ template to gcc

  1. #1
    Registered User
    Join Date
    Oct 2007
    Posts
    7

    Convert VisualC++ template to gcc

    Hello,
    trying to get some code converted from Visual C++ 6 to gcc.
    I've got pretty far, but as a C++ newbie I'm little bit lost with templates.

    It would be very nice if somebody could help me to get this working (with
    explanation please so I can learn).
    A possibility would also be to convert this template to a normal function
    (if it would help to get this working)

    Here is the template (table.h):
    Code:
    #ifndef _TABLE_H
    #define _TABLE_H
    
    #include <string>
    #include <vector>
    
    using namespace std;
    
    template <class T>
    class table: public vector<T>
    {
    public:
            T operator[] (const string& key);
    };
    
    
    template <class T>
    T table<T>::operator[] (const string& key)
    {
            for (reverse_iterator i = rbegin(); i != rend(); i++)
                    if (*i)
                            if ((*i)->name ^ key)
                                    return (T)((**i)());
            throw out_of_range("no elements matching key");
    }
    
     
    #endif
    Thanks in advance
    efgee

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You're converting some Visual C++ code (i.e., C++) for use with GCC (i.e., C)? Okay . . . that would require pretty much re-writing that whole code, because it uses std::strings.

    If you're converting Visual C++ code for use with g++ (i.e., still C++), then you probably don't have to do anything, because that code looks reasonably standards-compliant. (There are some issues, like the identifier _TABLE_H -- any identifier starting with _ followed by another _ or an uppercase letter is reserved by the implementation. I'd use TABLE_H.)
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you're not getting errors when compiling with g++, then you're done. If you are getting errors, post them.

    VC++ 6.0's template support does have a few issues, so it's possible that workarounds for that compiler will have to be removed for g++. An example is the use of typename before templated types. In VC++ 6.0 it fails if you use it, but standard C++ and a recent version of g++ require it. The only place I see that that might be happening is in your declaration of the reverse_iterator i. Perhaps typename reverse_iterator i will work better.

  4. #4
    Registered User
    Join Date
    Oct 2007
    Posts
    7
    Yeah stupid me I forgot to post the error messages, here they are.
    Regarding this line:
    Code:
    if ((*i)->name ^ *key)
    table.h: base operand of `->' is not a pointer
    table.h: no match for 'operator*' in '*key'

    And regarding this line:
    Code:
    return (T)((**i)());
    table.h: invalid type argument of `unary *'

    These are the last 3 errors I have, all the others are already ironed out.


    Thanks for your time and your help
    efgee

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    if ((*i)->name ^ *key)
    Your original code had no asterisk:
    Code:
    if ((*i)->name ^ key)
    Does it work better without it?

    > table.h: base operand of `->' is not a pointer
    Seems like perhaps table is expecting to have a pointer for its template type. How are you using this table?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    Code:
    #include <vector>
    
    using namespace std;
    
    template <class T>
    class table: public vector<T>
    {
    Should this be done? I forgot where I read it and I forgot the reason given (non-virtual dtor maybe?) but I think one should never derive from the std containers. Is this right or false?

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    It does seem that you shouldn't. But I didn't feel like reading this whole page.
    http://www.thescripts.com/forum/thread131388.html
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Registered User
    Join Date
    Oct 2007
    Posts
    7
    Wow, you guys/gals are fast.
    Thanks for the fast reply.

    Actually with the code posted above there have been more than 3 errors.
    The 3 errors mentioned are the ones I knew where pretty hard to solve.


    This is the code I have now and the errors are now down to 2 in total.

    Code:
    #ifndef _TABLE_H
    #define _TABLE_H
    
    #include <string>
    #include <vector>
    //the next line is for gcc
    #include <stdexcept>
    
    using namespace std;
    
    
    template <class T>
    class table: public vector<T>
    {
    public:
    	T operator[] (const string& key);
    };
    
    
    template <class T>
    T table<T>::operator[] (const string& key)
    {
        //the next line is for Visual C++
    	//for (reverse_iterator i = rbegin(); i != rend(); i++)
    
    	//the next line is for gcc
    	for (vector <int>::reverse_iterator i = key.rbegin(); i != key.rend(); i++)
    		if (*i)
    			if ((*i)->name ^ key)
    				return (T)((**i)());
    
    	throw out_of_range("no elements matching key");
    }
    
    #endif
    Here the error messages:
    Code:
    table.h: In member function `T table<T>::operator[](const std::string&)': 
    Line 29: table.h: base operand of `->' is not a pointer 
    Line 30: table.h: invalid type argument of `unary *'
    Line 29 and 30 are these 2 lines:
    Code:
    			if ((*i)->name ^ key)
    				return (T)((**i)());

    Thanks
    efgee
    Last edited by efgee; 10-03-2007 at 02:21 PM.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That error depends on the type T. What type are you using with your table?

    >> vector <int>::reverse_iterator
    Are you sure this is supposed to be vector <int> and not vector <T>? Did you try adding typename like I mentioned?

    If were using int as your type, then (*i)->name wouldn't work because int isn't a pointer and it doesn't have a member named "name" anyway.



    >> Should this be done?
    No, you are right. You shouldn't really derive from standard library containers, since they weren't intended to be base classes for dynamic polymorphism. As long as you aren't using them polymorphically (e.g. using vector<T> pointers or references that refer to table objects) then you'll be fine in practice, though.

    A better solution is to make the vector a member.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    What's that ^ doing there in the first place? You cannot apply ^ to a string. What weird type is the name member of whatever struct your vector contains pointers to, and why would it allow an ^ operation with strings as the right hand side? What are the semantics?

    Why implement a table (with weird element requirements) on top of a raw vector? Why use reverse iteration?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User
    Join Date
    Oct 2007
    Posts
    7
    Thank you all for your comments.

    Changed the 'For' code to:

    Code:
    for (typename vector <T>::reverse_iterator i = key.rbegin(); i != key.rend(); i++)
    now the compiler seems to run through this but I get tons of errors afterwards, because this template is used all over the place (that's what templates are for...).

    the error messages are like:
    Code:
    29 table.h: no match for 'operator!=' in 'i != std::basic_string<_CharT, _Traits, _Alloc>::rend() const [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]()'

    Regarding the ^: I don't know why the code was written in that way. It's a parser that parses through BASIC/PASCAL like code and generates C++ code.

    As a newbie I'm not even 100% sure what this template does ( I suppose iterating through a list of keywords and call a function depending on the keyword found).


    This code compiles with VS6 and VS2005 but I wanted to use gcc.

    Oh well...

    Thanks
    efgee

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Why did you switch to key.rbegin() and key.rend() rather than rbegin() and rend()? Those will do two different things. Using key.rbegin() will iterate through the characters in the string, using rbegin() will iterate through the values in the base class vector.

    If you don't know what you're doing, leave it as:
    Code:
    for (typename reverse_iterator i = rbegin(); i != rend(); i++)
    or if that doesn't work, then:
    Code:
    for (typename vector <T>::reverse_iterator i = rbegin(); i != rend(); i++)

    If the original code compiled and worked on VC++ 2005, then it should probably compile and work on gcc. I'd be surprised if VC++ 2005 allowed you to ignore the typename if the standard says its necessary. Similarly, the other things should fail on 2005.

  13. #13
    Registered User
    Join Date
    Oct 2007
    Posts
    7
    Thanks for your reply.

    This code:
    Code:
    for (typename reverse_iterator i = rbegin(); i != rend(); i++)
    gives this error message:
    Code:
    table.h: `reverse_iterator' does not name a type
    and this:
    Code:
    for (typename vector <T>::reverse_iterator i = rbegin(); i != rend(); i++)
    results in this error:
    Code:
    table.h: there are no arguments to `rbegin' that depend on a template parameter, so a declaration of `rbegin' must be available
    Surprisingly enough VS2005 didn't like other stuff like missing typecasting and such, but this template runs through as it does on VS6.

    Thanks again
    efgee

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Try this->rbegin() and this->rend(). Welcome to the wonderful world of dependent base classes.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  15. #15
    Registered User
    Join Date
    Oct 2007
    Posts
    7
    Yep, this seems to solve this.

    You guys/gals have been amazing, I appreciate your (everybody's) help.

    One last question though:

    What is better to use?

    this:
    Code:
    for (typename vector<T>::reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
    or this:
    Code:
    for (typename table<T>::reverse_iterator i = this->rbegin(); i != this->rend(); ++i)
    both seem to work.

    Again, thank you all.
    efgee

    (c++ newbie)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function template has already been defined
    By Elysia in forum C++ Programming
    Replies: 19
    Last Post: 04-14-2009, 10:17 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  5. Linked list with two class types within template.
    By SilasP in forum C++ Programming
    Replies: 3
    Last Post: 02-09-2002, 06:13 AM