Thread: mixing non-specialized and specialized templates

  1. #1
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838

    mixing non-specialized and specialized templates

    i'm writing an ADO-like wrapper class for SQLite. I'd like to emulate (and expand upon) their "AsType" methods, but i'm running into trouble mixing template specializations

    Code:
    template<> void castResult(String &arg,char *result)
    {
            arg = (String)result;
    }
    
    template<> void castResult(double &arg,char *result)
    {
            if(!TryStrToFloat(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to double");
            }
    }
    
    template<> void castResult(unsigned int &arg,char *result)
    {
            if(!TryStrToInt(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to int");
            }        
    }
    
    template<> void castResult(__int64 &arg,char *result)
    {
            if(!TryStrToInt64(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to double");
            }        
    }
    
    template<> void castResult(unsigned __int64 &arg,char *result)
    {
            if(!TryStrToInt64(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to double");
    
            }        
    }
    template<> void castResult(bool &arg,char *result)
    {
            if(!TryStrToBool(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to bool");
    
            }        
    }
    
    template<> void castResult(TDateTime &arg,char *result)
    {
            if(!TryStrToTime(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to TDateTime");
            }
    }
    
    template<> void castResult(int &arg,char *result)
    {
            if(!TryStrToInt(result,arg))
            {
                    throw Exception((String)result+"cannot be cast to double");
            }
    }
    
    
    template<typename T> T __fastcall field(char *colName)
    {
            T t;
            castResult<T>(t,results[colNumber(colName)+cols*recordOffset]);
            return t;
    }
    
    template<typename T> T __fastcall field(char *colName,unsigned int row)
    {
            if(row>=rows)
            {
                    invalidRow(row);
            }
            T t;
            return castResult(t,results[colNumber(colName)+cols*(row+1)]);
    }
    
    template<typename T> T __fastcall field(unsigned int col)
    {
            if(col>=cols)
            {
                    invalidCol(col);
            }
            T t;
            return castResult(t,results[col+cols*recordOffset]);
    }
    
    template<typename T> T __fastcall field(unsigned int col,unsigned int row)
    {
            if(row>=rows)
            {
                    invalidRow(row);
            }
            if(col>=cols)
            {
                    invalidCol(col);
            }
            T t;
            return castResult(t,results[cols*(row+1)+col]);
    }
    Code:
            sqlitedb::sqlResult *result = db.exec("select reportData.RPTID,reportData.SVID from reportData,eventReports where reportData.RPTID = eventReports.RPTID and eventReports.CEID = 0");
            unsigned int row = 1;
            while(!result->eof)
            {
                    int rptid = result->field<int>("RPTID");
                    int svid = result->field<int>("SVID");
                    row++;
                    result->next();
            }
            delete result;

    i've tried many different variations, including a T& as an argument to both field and castResult, but for some reason, my compiler won't deduce how to relate non-specialized and specialized templates.

    suggestions on the best way to proceed? i'd like not to have to specialize each of the 4 incarnations of field for each type.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Without effort you can't specialize a template function. Very rarely is the situation such that it is necessary. In most situations, simply overloading the function is correct.

    Just try 'castResult(t,results[colNumber(colName)+cols*recordOffset]);' in the relevant function.

    Soma

  3. #3
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    AFAICT that's what i've done. I have gotten all manner of odd errors. Including but not limited to:

    "call to undefined function castResult"

    "undefined symbol arg" <- this one really bothers me, in that it resolves to the appropriately specialized function, but then says it can't recognize its argument O_o

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I didn't even notice that you had called it differently in different functions.

    From 'field(char *, unsigned int)': 'castResult(t,results[colNumber(colName)+cols*(row+1)]);'.

    From ' field(char *)': 'castResult<T>(t,results[colNumber(colName)+cols*recordOffset]);'.

    Soma

  5. #5
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    err - yeah i was experimenting with different incarnations. i backed up to the point where i was getting "undefined symbol arg"

    the trick seems to be declaring a local variable and returning that (and changing the return types to return by value)


    Code:
    template<> int castResult(int d,char *result)
    {
            int d;
            if(!TryStrToInt(result,d))
            {
                    throw Exception((String)result+"cannot be cast to int");
            }
            return d;
    }
    
    //...
    
    template<typename T> T __fastcall field(char *colName)
    {
             T t;
             return castResult(t,results[colNumber(colName)+cols*recordOffset]);
    }
    
    //...
    
    int RPTID = result->field<int>("RPTID");
    i still don't understand why can't it recognize the function arguments.
    Last edited by m37h0d; 12-04-2008 at 09:22 PM. Reason: double --> int in exception message

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    What is the template<> doing in the castResult functions? Essentially it is not a template function / specialization.

    It should be possible, though, to use or create a templated converter (e.g boost::lexical_cast can convert anything to and from string as long as they have overloaded operator<< and >>, and anything you create based on stringstreams would too).
    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
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    ahh i get you; in this case, castresult has just been overloaded multiple times and they're not really specializations at all. i initially didn't want to supply a second argument to castResult, but specify which specialization to use as: castResult<T>(char *result), which does necessitate the use of templates AFAICT

    i do want one true template version of castresult though; so that in the event that the supplied type is not one specified, it will attempt the cast from char * to T.
    Last edited by m37h0d; 12-05-2008 at 04:16 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How properly get data out of vectors of templates?
    By 6tr6tr in forum C++ Programming
    Replies: 4
    Last Post: 04-15-2008, 10:35 AM
  2. Problem with overloaded function templates
    By New++ in forum C++ Programming
    Replies: 10
    Last Post: 09-05-2005, 04:00 PM
  3. templates and inheritance problem
    By kuhnmi in forum C++ Programming
    Replies: 4
    Last Post: 06-14-2004, 02:46 AM