Function template specialization?

This is a discussion on Function template specialization? within the C++ Programming forums, part of the General Programming Boards category; When compiling this code on VC++ 6.0 it gives me: Code: error C2667: 'StringToNum' : none of 2 overload have ...

  1. #1
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545

    Function template specialization?

    When compiling this code on VC++ 6.0 it gives me:
    Code:
    error C2667: 'StringToNum' : none of 2 overload have a best conversion
    error C2668: 'StringToNum' : ambiguous call to overloaded function
    Code:
    #include <string>
    #include <sstream>
    #include <stdexcept>
    #include <climits>
    
    template <typename E,
              typename T,
              typename A,
              typename N>
    void StringToNum( const std::basic_string<E, T, A>&  str,
                                                     N&  num )
    {
        std::basic_stringstream<E, T, A> ss( str );
    
        if ( !(ss >> num) )
        {
            throw std::invalid_argument( "Error converting string to number!" );
        }
    }
    
    template <typename E,
              typename T,
              typename A>
    void StringToNum( const std::basic_string<E, T, A>&  str,
                                         unsigned char&  num )
    {
        std::basic_stringstream<E, T, A> ss( str );
        unsigned short snum = 0;
    
        if ( !(ss >> snum) || (snum > UCHAR_MAX) )
        {
            throw std::invalid_argument( "Error converting string to number!" );
        }
        num = static_cast<unsigned char>( snum );
    }
    
    using namespace std;
    
    int main()
    {
        unsigned char num = 0;
        wstring str( L"Hello world" );
        StringToNum( str, num );
        return 0;
    }
    and on Comeau it's quite a bit more verbose...
    What's wrong and how can I make StringToNum() work for unsigned char numbers?

    When I tried compiling it without the specialization for unsigned chars I got this error:
    Code:
    error C2679: binary '>>' : no operator defined which takes a right-hand operand of type 'char' (or there is no acceptable conversion)
            D:\Programming\C++\Test\src\main.cpp(15) : see reference to function template instantiation 'class std::basic_istream<unsigned short,struct std::char_traits<unsigned short> > &__cdecl std::operator >>(class std::basic_istream<unsigned short,
    struct std::char_traits<unsigned short> > &,unsigned char &)' being compiled

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,581
    What function would the compiler choose if on the following template N was a unsigned char?

    Code:
    template <typename E,
              typename T,
              typename A,
              typename N>
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Mario F. View Post
    What function would the compiler choose if on the following template N was a unsigned char?

    Code:
    template <typename E,
              typename T,
              typename A,
              typename N>
    Since I provided a function that excplicitely takes an unsigned char, shouldn't it choose that one?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,271
    I tested cpjust's original code example with the MinGW port of g++ 3.4.5 and MSVC8, and it compiled without even a warning in both cases. However, it ran with an segfault in both cases too.
    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

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,581
    I believe he should do a partial specialization of the first template to take a unsigned char&.

    Code:
    template <typename E,
              typename T,
              typename A>
    void StringToNum<typename E, typename T, typename A, unsigned char&>( const std::basic_string<E, T, A>&  str, unsigned char&  num ) {
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    I tested cpjust's original code example with the MinGW port of g++ 3.4.5 and MSVC8, and it compiled without even a warning in both cases. However, it ran with an segfault in both cases too.
    Try using Comeau. It gives you pages of errors.

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Mario F. View Post
    I believe he should do a partial specialization of the first template to take a unsigned char&.

    Code:
    template <typename E,
              typename T,
              typename A>
    void StringToNum<typename E, typename T, typename A, unsigned char&>( const std::basic_string<E, T, A>&  str, unsigned char&  num ) {
    That didn't work. This is on VC++ 6.0, so maybe that has something to do with it also...

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,271
    I believe he should do a partial specialization of the first template to take a unsigned char&.
    From what I understand C++ does not have partial function template specialisation at the moment.

    Try using Comeau. It gives you pages of errors.
    Yes, I did. I wanted to point out an inconsistency here with two other compilers that are reasonably standard conformant.
    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

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,581
    Quote Originally Posted by cpjust View Post
    That didn't work.
    Nor it should. I'm sorry. Copyed paste code in a whim and didn't check my post properly. If anything you wouldn't need the arguments declaration. But you have a function template there. Not a class template. So I did even worst, function templates can't be partially specialized.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  10. #10
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    I tested cpjust's original code example with the MinGW port of g++ 3.4.5 and MSVC8, and it compiled without even a warning in both cases. However, it ran with an segfault in both cases too.
    Oh, I think I might know why it crashed. Change the string to "255" instead of "Hello world".

    Anyways, I found a workable, but slightly less desirable solution:
    Code:
    template <typename E,
              typename T,
              typename A,
              typename N>
    void StringToNum( const std::basic_string<E, T, A>&  str,
                                                     N&  num )
    {
        std::basic_stringstream<E, T, A> ss( str );
        long lnum = 0;
    
        if ( !(ss >> lnum) || (lnum < std::numeric_limits<N>::min()) || (lnum > std::numeric_limits<N>::max()) )
        {
            throw std::invalid_argument( "Error converting string to number!" );
        }
    
    	num = static_cast<N>( lnum );
    }
    BTW, I tried using long long int lint = 0; but VC++ 6.0 said I can't say long twice.
    I've seen that used in other examples to get 64-bit integers... Is long long standard, or is it a compiler extension?

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,013
    __int64 would do the trick on Microsoft compilers.
    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.

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,581
    It's currently an extension on some C++ compilers.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    There probably isn't a basic_stringstream overload for operator>>() for 64-bit ints anyways, so maybe I'd better keep it as a long.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,013
    Sure, there is.
    Code:
    std::stringstream s;
    s << (uint64_t)0; // Works
    s << (int64_t)0; // Works
    uint64_t n;
    s >> n; // Works
    s >> (int64_t)n; // Doesn't work! :(
    At least on Microsoft's compilers.
    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.

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    Sure, there is.
    Code:
    std::stringstream s;
    s << (uint64_t)0; // Works
    s << (int64_t)0; // Works
    uint64_t n;
    s >> n; // Works
    s >> (int64_t)n; // Doesn't work! :(
    At least on Microsoft's compilers.
    I think they key phrase there is "At least on Microsoft's compilers".
    I tried using a long long with stringstreams on Comeau and it didn't have an operator>>() for long long.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  2. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  3. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 09:39 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 07:39 AM
  5. C++ compilation issues
    By Rupan in forum C++ Programming
    Replies: 1
    Last Post: 08-22-2005, 06:45 AM

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