 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Burnce Guest
|
Posted: Thu Jan 13, 2005 12:20 pm Post subject: Template function problem |
|
|
Hi,
I have a problem relating to template resolution.
I am writing some templates to be able to package objects into messages
for communication.
template <typename T>
int packSize(const T& data){
...
}
template<typename T>
void pack(const T& data, char* buffer, int bufferLength, int* position){
...
}
template<typename T>
T unpack(char* buffer, int bufferLength, int* position){
...
}
I would like to be able to send STL objects... therefore I have written:
template<>
int packSize(const string& data){
...
}
template<>
void pack(const string& data, char* buffer, int bufferLength, int* position){
...
}
template<>
string unpack<string>(char* buffer, int bufferLength, int* position,){
...
}
And for the vector class:
template<typename U>
int packSize(const vector<U>& data){
...
}
template<typename U>
void pack(const vector<U>& data,
char* buffer,
int bufferLength,
int* position){
...
}
Up to here things work fine. I can call:
string C = unpack<string>(data, buffer, length, &position);
But when I add this
template<typename U>
vector<U> unpack(char* buffer, int bufferLength, int* position){
...
}
As long as I dont call unpack still things are fine. But if I call:
string C = unpack<string>(data, buffer, length, &position);
I get an error at compile time:
call of overloaded `unpack(char*&, int&, int*)' is ambiguous
candidates are:
T unpack(char*, int, int*) [with T = std::string]
std::vector<U, std::allocator<_CharT> > unpack(char*, int, int*)
[with U = std::string]
Is there a way to get around this? Is there a way to make
unpack<string>() call the first unpack template and unpack<vector()
or unpack<vector call the second?
Thanks in advance,
Burnce
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ciprian Ciubotariu Guest
|
Posted: Thu Jan 13, 2005 8:39 pm Post subject: Re: Template function problem |
|
|
First I got a question for standard gurus: why is the syntax
template<class> void f<string>(...) accepted for functions? Is it a
compiler problem, or does the standard allow it?
I think the main reason why your program fails to compile is that
functions cannot be explicitly specialized, only overloaded. Overload
resolution is only dependent on the function parameters. (see 13.1
[over.load], paragraph 2)
The difference between packSize, pack and unpack is that the first two
have overloads for T, std::string, vector<U>. The unpack is badly
overloaded (since you can't overload only based on return value) and the
program is ill-formed (if i understand the C++ standard correctly).
Since you specify explicit arguments to your call to unpack (i.e.
unpack<string>) the compiler only considers template<class T> T
unpack(...) and template<class U> vector<U> unpack(...) and not
std::string unpack(...). If you try calling string C = unpack(...) you
will get ambiguity for all "overloads" of unpack.
My personal solution to this problem is to use class template
specializations if you really need a return type.
template<class T> struct unpack {
static T unpack(...);
};
template<> struct unpack<string> {
static string unpack(...);
};
template<class U> struct unpack<vector {
static vector<U> unpack(...);
};
A better idea might be to add an "out" parameter to unpack, thus
bringing the "return value" into the parameter list of unpack:
template<class T> void unpack(..., T& result);
template<class U> void unpack(..., vector<U>& result);
void unpack(..., string & result);
Cheers,
Cipi
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Sat Jan 15, 2005 2:59 am Post subject: Re: Template function problem |
|
|
Burnce wrote:
| Quote: | I have a problem relating to template resolution.
I am writing some templates to be able to package objects into
messages for communication.
|
[...]
| Quote: | template<typename T
T unpack(char* buffer, int bufferLength, int* position){
...
}
I would like to be able to send STL objects... therefore I have
written: |
[...]
| Quote: | template
string unpack
position,){
...
}
And for the vector class:
|
[...]
| Quote: | Up to here things work fine. I can call:
string C = unpack<string>(data, buffer, length, &position);
But when I add this
template<typename U
vector
position){
...
}
As long as I dont call unpack still things are fine. But if I call:
string C = unpack<string>(data, buffer, length, &position);
I get an error at compile time:
call of overloaded `unpack(char*&, int&, int*)' is ambiguous
candidates are:
T unpack(char*, int, int*) [with T = std::string]
std::vector<U, std::allocator<_CharT> > unpack(char*, int,
int*)
[with
U = std::string] |
Well, you have two overloaded function templates, and both are
an exact match, so I don't quite see how it could be anything
but ambiguous.
| Quote: | Is there a way to get around this? Is there a way to make
unpack<string>() call the first unpack template and
unpack<vector() or unpack<vector call the
second?
|
That no, but you could have unpack return a proxy class with a
templated conversion operator -- it's the standard way of
forcing the what you do with the return type to influence
overloading. Just a single global function unpack with:
class UnpackProxy
{
public:
UnpackProxy( char const* buffer,
int length,
int* position )
: myBuffer( buffer )
, myLength( length )
, myPosition( position )
{
}
template< typename T > operator T() const
{
return Unpacker< T >()( myBuffer, myLength, myPosition ) ;
}
} ;
inline UnpackProxy unpack(
char const* buffer, int bufferLength, int* position )
{
return UnpackProxy( buffer, bufferLength, position ) ;
}
At this point, all you have to write is:
std::string s = unpack( buffer, size, pos ) ;
// eventually calls Unpacker< std::string >()( ... )
std::vector< int > v = unpack( buffer, size, pos ) ;
// eventually calls Unpacker< std::vector< int > >()( ... )
With regards to supporting standard containers, I would
certainly investigate some sort of partial specialization
depending on whether the type in question had member functions
begin() and end() or not (or maybe whether there was a type
T::iterator). (I'm not too sure how to do this, but I'm pretty
sure that is has been done somewhere.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
msalters Guest
|
Posted: Sat Jan 15, 2005 3:01 am Post subject: Re: Template function problem |
|
|
Ciprian Ciubotariu wrote:
| Quote: | First I got a question for standard gurus: why is the syntax
template<class> void f<string>(...) accepted for functions? Is it a
compiler problem, or does the standard allow it?
|
I think the syntax is allowed, but it still should give an error.
Some rules are just too hard to express in syntax form.
In this case, the two applicable parts are
templatedeclaration:
export(opt) template < templateparameterlist> declaration (from 14)
and
explicitspecialization:
template < > declaration (14.7.3)
As you see, the syntax requires a declaration in both cases.
However, the extra (non-syntax) rules differ for these two cases.
| Quote: | I think the main reason why your program fails to compile is that
functions cannot be explicitly specialized, only overloaded.
|
Wrong, 14.7.3 Explicit specialization even starts with function
templates.
Regards,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ciprian Ciubotariu Guest
|
Posted: Tue Jan 18, 2005 11:14 pm Post subject: Re: Template function problem |
|
|
msalters wrote:
| Quote: | Ciprian Ciubotariu wrote:
First I got a question for standard gurus: why is the syntax
template<class> void f<string>(...) accepted for functions? Is it a
compiler problem, or does the standard allow it?
I think the syntax is allowed, but it still should give an error.
Some rules are just too hard to express in syntax form.
In this case, the two applicable parts are
templatedeclaration:
export(opt) template < templateparameterlist> declaration (from 14)
and
explicitspecialization:
template < > declaration (14.7.3)
As you see, the syntax requires a declaration in both cases.
However, the extra (non-syntax) rules differ for these two cases.
|
I think this could be moved into the syntax rules if using two separate
versions of "declaration" (and maybe "specialization-declaration").
| Quote: |
I think the main reason why your program fails to compile is that
functions cannot be explicitly specialized, only overloaded.
Wrong, 14.7.3 Explicit specialization even starts with function
templates.
Regards,
Michiel Salters
|
You are correct; it was an attempt to partially specialize a function
template actually... It's interesting how I totally forgot that complete
specializations are allowed for function templates Thanks for
reminding me.
Cipi
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|