Const pointers/references

This is a discussion on Const pointers/references within the C++ Programming forums, part of the General Programming Boards category; Hello everyone! I have this interesting problem. Here is my code: Code: template <class T> int compare (const T& a, ...

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    69

    Const pointers/references

    Hello everyone!

    I have this interesting problem. Here is my code:

    Code:
    template <class T>
    int compare (const T& a, const T& b)
    {
      if (a == b)
        return (0);
      return (a > b ? -1 : 1);
    }
    
    template <>
    int compare<const char *>(const char* const & a, const char* const & b)
    {
      int   x;
    
      x = strcmp(a, b);
      if (x == 0)
        return (x);
      else if (x > 0)
        return (-1);
      return (1);
    }
    
    template <>
    int compare<char *>(char* const & a, char* const & b)
    {
      int   x;
    
      x = strcmp(a, b);
      if (x == 0)
        return (x);
      else if (x > 0)
        return (-1);
      return (1);
    }
    main.cpp
    Code:
    class toto
    {
        toto &operator=(const toto&) {return *this;}
        toto(const toto &){}
        public:
        bool operator==(const toto&) const {return true;}
        bool operator>(const toto&) const {return false;}
        bool operator<(const toto&) const {return false;}
        toto(){}
    };
    
    int main()
    {
         toto a, b;
    
         compare(a, b);
         compare(1, 2);
         compare(static_cast<const char*>("string1"), static_cast<const char *>("string2"));
         return (0);
    }
    My question:

    I was forced to declare one of the compare functions with (const char * const &a). I don't understand at all why... the string declared this way "string", is const char * by default, no? And even with the cast, its still const char* - so why the double const?

    Thank you.

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,456
    The problem is with the placement of const and what it applies to.
    When you write const char*, the const applies to the type the pointer points it, ie a pointer to const. However, the pointer itself isn't const. And C++ rules say that temporaries can only be passed by const reference. Therefore, the const must be placed after the * to apply to the pointer itself.

    Type modifier name

    This is the general declaration of a variable.
    Note that anything that is left of the modifier, in our case, the *, is part of the type.
    Anything after the modifier applies to the variable, and not the type.
    And the standard dictates that to pass a temporary value by reference, it must be a constant reference (ie not a reference to a pointer, but rather a const reference to pointer).
    Last edited by Elysia; 09-14-2009 at 11:13 AM.
    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.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    69
    Alright, and in this case why does:

    compare("string1", "string2");

    call the compare (const T& a, const T& b) and not the:

    compare<char *>(char* const & a, char* const & b).

    string1 is a char*, and its temporary so the reference is const.

    Any idea?

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,456
    "string1" is const char[8], not char* nor const char*.
    It simply is implicitly converted to const char* / char* when passed to a function that accepts such a type.
    In this case, const T& matches the type better because it doesn't have to perform an implicit conversion.

    Add in a const char[N] overload and you'll see it gets called.
    Last edited by Elysia; 09-14-2009 at 11:41 AM.
    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.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,457
    Quote Originally Posted by +Azazel+
    string1 is a char*
    "string1" is a const char[8].
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Try what happens if you don't specialize but overload. It would be interesting if someone posted an explanation what's the difference.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    2,021
    If you overload with an non-template, it will prefer the non-template when compatible. This is the common solution.

    You can also overload with this:
    Code:
    template <int N, int M>
    int compare (const char (&a)[N], const char (&b)[M] ) 
    ...
    Last edited by King Mir; 09-14-2009 at 12:28 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  8. #8
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,456
    Sometimes I wonder about the fine line between template specializing and overloading. I suppose specializing is best where some argument are still dependent on an unknown type, while overloading is good when you know the type of all its arguments.
    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
    Apr 2006
    Posts
    2,021
    My book says that template specialization is only for classes. So I'm now confused why the OP syntax works.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,457
    Quote Originally Posted by King Mir
    My book says that template specialization is only for classes. So I'm now confused why the OP syntax works.
    You might have missed the word "partial" in your book.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If you overload with an non-template, it will prefer the non-template when compatible.
    But it is compatible only after a pointer decay?

    Sometimes I wonder about the fine line between template specializing and overloading. I suppose specializing is best where some argument are still dependent on an unknown type, while overloading is good when you know the type of all its arguments.
    I think one should practically never specialize function templates. It doesn't buy you anything and can only lead to confusion such as here. If I'm not mistaken, an exception might be when you want to add specializations to std namespace (e.g custom swap), since technically it is not correct to add overloads to std namespace. (However, it appears that if you overload swap for a template class, then there is no way to legally add it to std namespace.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    If I'm not mistaken, an exception might be when you want to add specializations to std namespace (e.g custom swap), since technically it is not correct to add overloads to std namespace.
    That's what ADL is for. Overload swap in the namespace of your class, and never explicitly qualify calls to swap (or use boost::swap).
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Drawing Program
    By Max_Payne in forum C++ Programming
    Replies: 21
    Last Post: 12-21-2007, 04:34 PM
  4. Certain functions
    By Lurker in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2003, 12:26 AM
  5. Half-life SDK, where are the constants?
    By bennyandthejets in forum Game Programming
    Replies: 29
    Last Post: 08-25-2003, 11:58 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21