By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,563 Members | 1,280 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,563 IT Pros & Developers. It's quick & easy.

template functions and "return type overloading"

P: n/a
I have the following code segment - which compiles fine. I'm just
worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

.... etc.

Jul 23 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just
It shouldn't. You cannot overload functions on their return value only:

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

int main()
{
int a = getValue(1, 2);
}

"ComeauTest.c", line 9: error: more than one instance of overloaded
function
"getValue" matches the argument list, the choices that match
are:
function template "getValue(T1, T2)"
function template "getValue(T1, T2)"
The argument types that you used are: (int, int)
int a = getValue(1, 2);

It will compile until you try to call one of the overloads.
worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?
No.
template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

... etc.


What are you trying to achieve?
Jonathan

Jul 23 '05 #2

P: n/a
> I have the following code segment - which compiles fine. I'm just
worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

... etc.


Hmm, I must say I am surprised that these declarations compile. But bear in
mind there are all but template declaration nevertheless. The compiler won't
issue any error until it has to instantiate the template, such as an
explicit template instantiation or a call to the function template:

template int getValue(int, int); // error
int a = getValue(1,2); // error

Regards,
Ben
Jul 23 '05 #3

P: n/a


Jonathan Mcdougall wrote:
Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just

It shouldn't. You cannot overload functions on their return value only:

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

int main()
{
int a = getValue(1, 2);
}

"ComeauTest.c", line 9: error: more than one instance of overloaded
function
"getValue" matches the argument list, the choices that match
are:
function template "getValue(T1, T2)"
function template "getValue(T1, T2)"
The argument types that you used are: (int, int)
int a = getValue(1, 2);

It will compile until you try to call one of the overloads.

worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?

No.

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

... etc.

What are you trying to achieve?
Jonathan


I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks

Jul 23 '05 #4

P: n/a
Ann Huxtable wrote:
Jonathan Mcdougall wrote:
Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just


It shouldn't. You cannot overload functions on their return value only:
What are you trying to achieve?


I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks


Include the return in the template list:

#include <string>
#include <sstream>

template <class Ret, class T1, class T2>
Ret getValue(T1 col, T2 row)
{
std::string value = get_value_from_db_as_string(col, row);

std::istringstream iss(value);
Ret r = Ret();

iss >> r;

return r;
}

int main()
{
int a = getValue<int>(10, 10);
double b = getValue<double>(11, 11);
Image c(getValue<Image>(12, 12)); // provided Image overloaded the
operator>>
}

If you cannot get the value as a string from the database, you'll have
to find another way. Come back if you didn't find any.
Jonathan

Jul 23 '05 #5

P: n/a


Jonathan Mcdougall wrote:
Ann Huxtable wrote:
Jonathan Mcdougall wrote:

Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just

It shouldn't. You cannot overload functions on their return value only:
What are you trying to achieve?


I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks

Include the return in the template list:

#include <string>
#include <sstream>

template <class Ret, class T1, class T2>
Ret getValue(T1 col, T2 row)
{
std::string value = get_value_from_db_as_string(col, row);

std::istringstream iss(value);
Ret r = Ret();

iss >> r;

return r;
}

int main()
{
int a = getValue<int>(10, 10);
double b = getValue<double>(11, 11);
Image c(getValue<Image>(12, 12)); // provided Image overloaded the
operator>>
}

If you cannot get the value as a string from the database, you'll have
to find another way. Come back if you didn't find any.
Jonathan


The database example I gave was just a conceptul illustration. I will
not necesarily be loading data from a db. I think the simplest
implementation would be to create templated functions (for each of the
data types supported - i.e. getString(), getLong(), getNestedTable() etc.

Thanks for your help nonetheless ..

Jul 23 '05 #6

P: n/a

"Ann Huxtable" <an*********@research.de.edu> wrote in message
news:db**********@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com...


Jonathan Mcdougall wrote:
Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just

It shouldn't. You cannot overload functions on their return value only:

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

int main()
{
int a = getValue(1, 2);
}

"ComeauTest.c", line 9: error: more than one instance of overloaded
function
"getValue" matches the argument list, the choices that match
are:
function template "getValue(T1, T2)"
function template "getValue(T1, T2)"
The argument types that you used are: (int, int)
int a = getValue(1, 2);

It will compile until you try to call one of the overloads.

worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?

No.

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

... etc.

What are you trying to achieve?
Jonathan


I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks


Now, what you described is indeed three problems: input types, output types,
and extensibility. Let's take them apart:

You are looking for int-int, int-string, string-int, string-string pairs as
input type and are looking for extensibility, if I correctly understand your
post. The ideal way is to use the C++ type system to help you. What's in my
mind is a single concept for locating a cell, say, cell_entry:

class cell_entry_base
{
protected:
cell_entry_base();
// whatever you need to know to locate a cell
};

// map to col-row pair types
template <typename ColT, typename RowT>
class cell_entry;

// specialize for <int, int>
template <> class cell_entry<int, int>: public cell_entry_base
{
//...
};

// also specialize for <int, string>, <string, int> and <string, string>
//...

// also specialize for other types you wish, extending made easy...

Now the output type. You need to map a set of C++ type to the internal types
supported by the database, if I am still on the track. So I came up with
traits:

template <typename T>
class entry_type_trait;

template <> class entry_type_trait<char*>
{
public:
static char* get_value(cell_entry_base&) throw (bad_type)
{
// your database access code here,
// throw bad_type if type not matched
}

//... more ops up to you
};

// also specialize for <int> <double> and <void*>
// ...

Note that you only have to add a new specialization to extend the type
mapping. And finally the function getValue can be trivially implemented:

template <typename ReturnT, typename ColT, typename RowT>
ReturnT getValue(ColT col, RowT row) throw (bad_type)
{
cell_entry<ColT, RowT> entry(col, row); // enforce input types
return entry_type_trait<ReturnT>::get_value(entry); // output
types
}

Regards,
Ben
Jul 23 '05 #7

P: n/a


benben wrote:
"Ann Huxtable" <an*********@research.de.edu> wrote in message
news:db**********@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com...

Jonathan Mcdougall wrote:

Ann Huxtable wrote:
I have the following code segment - which compiles fine. I'm just
It shouldn't. You cannot overload functions on their return value only:

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

int main()
{
int a = getValue(1, 2);
}

"ComeauTest.c", line 9: error: more than one instance of overloaded
function
"getValue" matches the argument list, the choices that match
are:
function template "getValue(T1, T2)"
function template "getValue(T1, T2)"
The argument types that you used are: (int, int)
int a = getValue(1, 2);

It will compile until you try to call one of the overloads.

worried I may get run time probs - because it looks like the functions
are being overloaded by the return types?. Is this Ok: ?
No.

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

template <class T1, class T2>
std::string getValue( T1 col, T2 row ) ;

template <class T1, class T2>
Table getValue( T1 col, T2 row ) ;

... etc.
What are you trying to achieve?
Jonathan


I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks

Now, what you described is indeed three problems: input types, output types,
and extensibility. Let's take them apart:

You are looking for int-int, int-string, string-int, string-string pairs as
input type and are looking for extensibility, if I correctly understand your
post. The ideal way is to use the C++ type system to help you. What's in my
mind is a single concept for locating a cell, say, cell_entry:

class cell_entry_base
{
protected:
cell_entry_base();
// whatever you need to know to locate a cell
};

// map to col-row pair types
template <typename ColT, typename RowT>
class cell_entry;

// specialize for <int, int>
template <> class cell_entry<int, int>: public cell_entry_base
{
//...
};

// also specialize for <int, string>, <string, int> and <string, string>
//...

// also specialize for other types you wish, extending made easy...

Now the output type. You need to map a set of C++ type to the internal types
supported by the database, if I am still on the track. So I came up with
traits:

template <typename T>
class entry_type_trait;

template <> class entry_type_trait<char*>
{
public:
static char* get_value(cell_entry_base&) throw (bad_type)
{
// your database access code here,
// throw bad_type if type not matched
}

//... more ops up to you
};

// also specialize for <int> <double> and <void*>
// ...

Note that you only have to add a new specialization to extend the type
mapping. And finally the function getValue can be trivially implemented:

template <typename ReturnT, typename ColT, typename RowT>
ReturnT getValue(ColT col, RowT row) throw (bad_type)
{
cell_entry<ColT, RowT> entry(col, row); // enforce input types
return entry_type_trait<ReturnT>::get_value(entry); // output
types
}

Regards,
Ben


Ok, this looks interesting, I'm re-reading your post to make sure I
understand it completely (BTW, I believe you are on the right track -
i.e. you *did understand the problem posed). If I encounter any probs
with your solution, I'll be right back. tks

Jul 23 '05 #8

P: n/a


Ann Huxtable wrote:


benben wrote:
"Ann Huxtable" <an*********@research.de.edu> wrote in message
news:db**********@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com...

Jonathan Mcdougall wrote:
Ann Huxtable wrote:
> I have the following code segment - which compiles fine. I'm just

It shouldn't. You cannot overload functions on their return value only:

template <class T1, class T2>
int getValue( T1 col, T2 row ) ;

template <class T1, class T2>
double getValue( T1 col, T2 row ) ;

int main()
{
int a = getValue(1, 2);
}

"ComeauTest.c", line 9: error: more than one instance of overloaded
function
"getValue" matches the argument list, the choices that match
are:
function template "getValue(T1, T2)"
function template "getValue(T1, T2)"
The argument types that you used are: (int, int)
int a = getValue(1, 2);

It will compile until you try to call one of the overloads.

> worried I may get run time probs - because it looks like the functions
> are being overloaded by the return types?. Is this Ok: ?

No.

> template <class T1, class T2>
> int getValue( T1 col, T2 row ) ;
>
> template <class T1, class T2>
> double getValue( T1 col, T2 row ) ;
>
> template <class T1, class T2>
> std::string getValue( T1 col, T2 row ) ;
>
> template <class T1, class T2>
> Table getValue( T1 col, T2 row ) ;
>
> ... etc.

What are you trying to achieve?
Jonathan
I'm writing a "Table" class which mimics a table returned in an SQL
query. The only difference is that in my table, I want to be able to
nest tables within tables - so some columns will contain other table.

To answer your question regarding whT i'm trying to achieve, the
templated functions above are retriving the values stored in a cell. The
cell is currently implemented as a union (although I may change to the
Boost variant type at a later stage). The cell can store one of the
following types:

char*
int,
double
void * //To allow nesting
Cells are referenced by (row,col) where each of the parameters could
either be a string (name) or int (index). This permutated with the large
number of possible return variables will result in 4*4 = 16 functions
just to get a value, and then another 16 to set a value - and this is
not easily extensible if I need to store other variable types. Hence my
post.

If you have any ideas as to how to solve this problem, I'd be willing to
hear them. Tks

Now, what you described is indeed three problems: input types, output
types,
and extensibility. Let's take them apart:

You are looking for int-int, int-string, string-int, string-string
pairs as
input type and are looking for extensibility, if I correctly
understand your
post. The ideal way is to use the C++ type system to help you. What's
in my
mind is a single concept for locating a cell, say, cell_entry:

class cell_entry_base
{
protected:
cell_entry_base();
// whatever you need to know to locate a cell
};

// map to col-row pair types
template <typename ColT, typename RowT>
class cell_entry;

// specialize for <int, int>
template <> class cell_entry<int, int>: public cell_entry_base
{
//...
};

// also specialize for <int, string>, <string, int> and <string,
string>
//...

// also specialize for other types you wish, extending made easy...

Now the output type. You need to map a set of C++ type to the internal
types
supported by the database, if I am still on the track. So I came up with
traits:

template <typename T>
class entry_type_trait;

template <> class entry_type_trait<char*>
{
public:
static char* get_value(cell_entry_base&) throw (bad_type)
{
// your database access code here,
// throw bad_type if type not matched
}

//... more ops up to you
};

// also specialize for <int> <double> and <void*>
// ...

Note that you only have to add a new specialization to extend the type
mapping. And finally the function getValue can be trivially implemented:

template <typename ReturnT, typename ColT, typename RowT>
ReturnT getValue(ColT col, RowT row) throw (bad_type)
{
cell_entry<ColT, RowT> entry(col, row); // enforce input
types
return entry_type_trait<ReturnT>::get_value(entry); // output
types
}

Regards,
Ben


Ok, this looks interesting, I'm re-reading your post to make sure I
understand it completely (BTW, I believe you are on the right track -
i.e. you *did understand the problem posed). If I encounter any probs
with your solution, I'll be right back. tks


This is quite an elegant approach (albeit a bit confusing - to me
atleast). You may hev been also led slight astray by the special case of
loading data from a database into this memory table - however, the
proposed implimentation is still apropriate nonetheless.

Would you care to elaborate exactly what the base class cell_entry_base
does (you noted: // whatever you need to know to locate a cell). I'd
also be grateful if you add a little more flesh (or at least comments to
the template specializations for class cell_entry). It is likely that I
may have to come back to you several times during my implementation - I
hope you don't mind :-) (please indicate if you are too busy to assist
- though, in which case I'll keep it simple and use my less elegant
method - but I really like this more compact approach...)

Jul 23 '05 #9

P: n/a
> This is quite an elegant approach (albeit a bit confusing - to me
atleast). You may hev been also led slight astray by the special case of
loading data from a database into this memory table - however, the
proposed implimentation is still apropriate nonetheless.

Would you care to elaborate exactly what the base class cell_entry_base
does (you noted: // whatever you need to know to locate a cell). I'd
also be grateful if you add a little more flesh (or at least comments to
the template specializations for class cell_entry). It is likely that I
may have to come back to you several times during my implementation - I
hope you don't mind :-) (please indicate if you are too busy to assist
- though, in which case I'll keep it simple and use my less elegant
method - but I really like this more compact approach...)


I am glad I have been a littel helpful.

The class cell_entry_base is designed to consist any data or operation that
is necessary to locate a cell in your database. This is highly
implementation dependent--how it is implemented is directly related to the
database you are using. In situations where multi-connection, multi-table
database are concerned, you probably have to elaborate the class even a
little further.

That said, if your database can always use an int-int pair to locate a cell
directly, cell_entry_base is quite triviall:

class cell_entry_base
{
public:
int col;
int row;

// ...
};
Regards,
Ben
Jul 23 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.