Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss
Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

function template resolution

0 views
Skip to first unread message

Alex Vinokur

unread,
Feb 10, 1999, 3:00:00 AM2/10/99
to
In article <79qv2d$6it$1...@ns2.kow.khi.co.jp>,
"T.Yoshida" <yosh...@giw.khi.co.jp> wrote:
> Given the following two function templates:
>
> template < class T1, class T2 > int f( T2 ); // #1
> template < class T2 > int f( T2 ); // #2
>
> how the function call below is to be resolved?
>
> f<float>( 1.0F );
>
> (1) f<float,float>(float)
>
> (2) f<float>(float)
>
> (3) Ambiguous
>
> I feel it should resolve to (2) since it does not require template argument
> deduction and I feel the resolution which does not require template argument
> deduction should have precedence over the one which requires the deduction.
> But I can not find such a precedence rule in the standard document.
>
> At best, I think it should be flagged as error because of the ambiguity.
> Still, a certain C++ compiler in the market resolves it to (1).
>
> Can someone explain which is correct in the light of the C++ standard with
> good rationale?
>
> -----------------------------------------------------------------
> Tsutomu Yoshida
> Minokamo, Japan
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
>


Hi,

There is a difference between

A.1) syntax of template (usual) function without arguments
A.2) syntax of template (usual) function with some (not all) arguments
A.3) syntax of template (usual) function with all arguments

B.1) syntax of template member function without arguments
B.2) syntax of template member function with some (not all) arguments
B.3) syntax of template member function with all arguments


This difference is demonstrated in the following example.

Alex

###################################################
############# 1. jp_class.H #######################
###################################################

#include <string>


//############################################
// template (usual) function without arguments
template <typename T1, typename T2>
void foo_no()
{
cout << __PRETTY_FUNCTION__ << " \t: No input parameters" << endl;
// __PRETTY_FUNCTION__ is predefined string variable in gcc/g++
}


//############################################
// template (usual) function only with first argument
template <typename T1, typename T2>
void foo_1(T1 &first)
{
cout << __PRETTY_FUNCTION__ << " \t: arg1 = " << first << endl;
}


//############################################
// template (usual) function only with second argument
template <typename T1, typename T2>
void foo_2(T2 &second)
{
cout << __PRETTY_FUNCTION__ << " \t: arg2 = " << second << endl;
}

//############################################ // template (usual) function
with all arguments template <typename T1, typename T2> void foo_all(T1
&first, T2 &second) { cout << __PRETTY_FUNCTION__ << " \t: arg1 = " << first
<< ", arg2 = " << second << endl; }

//############################################
class MyClass
{
public:
MyClass () {}
~MyClass () {}

//------------------------------------------
// template member function without arguments
template <typename T1, typename T2>
void Foo_no();

//------------------------------------------
// template member function only with first argument
template <typename T1, typename T2>
void Foo_1(T1 &first);

//------------------------------------------
// template member function only with second argument
template <typename T1, typename T2>
void Foo_2(T2 &second);

//------------------------------------------
// template member function only with all arguments
template <typename T1, typename T2>
void Foo_all(T1 &first, T2 &second);
};

//############################################
// template member function without arguments
template <typename T1, typename T2>
void MyClass::Foo_no()
{
cout << __PRETTY_FUNCTION__ << " \t: No input parameters" << endl;
}


//############################################
// template member function only with first argument
template <typename T1, typename T2>
void MyClass::Foo_1(T1 &first)
{
cout << __PRETTY_FUNCTION__ << " \t: Arg1 = " << first << endl;
}


//############################################
// template member function only with second argument
template <typename T1, typename T2>
void MyClass::Foo_2(T2 &second)
{
cout << __PRETTY_FUNCTION__ << " \t: Arg2 = " << second << endl;
}

//############################################ // template member function
with all arguments template <typename T1, typename T2> void
MyClass::Foo_all(T1 &first, T2 &second) { cout << __PRETTY_FUNCTION__ << "
\t: Arg1 = " << first << ", Arg2 = " << second << endl; }

###################################################
############# 2. MyClass.cpp ######################
###################################################

#include "jp_class.H"
// The file has no implementation (in this example)

###################################################
############# 3. jp_main.C ########################
###################################################

#include "jp_class.H"
int main ()
{
MyClass object;

int i11 = 11;
int i12 = 12;
int i21 = 21;
int i22 = 22;
int i31 = 31;
int i32 = 32;
int i41 = 41;
int i42 = 42;

char* c11 = "one_aaaaa";
char* c12 = "one_bbbbb";
char* c21 = "two_aaaaa";
char* c22 = "two_bbbbb";
char* c31 = "three_aaaaa";
char* c32 = "three_bbbbb";
char* c41 = "four_aaaaa";
char* c42 = "four_bbbbb";


//##############################################
//##############################################
cout << endl;
cout << endl;
cout << "###### foo_no : template (usual) function without arguments
######" << endl;
cout << " All template types are explicit" << endl;
foo_no<int, int> ();
foo_no<int, char*> ();
foo_no<char*, int> ();
foo_no<char*, char*> ();

//==============================================
cout << endl;
cout << endl;
cout << "###### foo_1 : template (usual) function only with first
argument ######" << endl;
cout << " All template types are explicit" << endl;
foo_1<int, int> (i11);
foo_1<int, char*> (i21);
foo_1<char*, int> (c31);
foo_1<char*, char*> (c41);

//==============================================
cout << endl;
cout << endl;
cout << "###### foo_2 : template (usual) function only with second
argument ######" << endl;
cout << " All template types are explicit" << endl;
foo_2<int, int> (i12);
foo_2<int, char*> (c22);
foo_2<char*, int> (i32);
foo_2<char*, char*> (c42);

cout << endl;
cout << " First template type is explicit" << endl;
cout << " Second template type is implicit (defined according to the
arg2 type)" << endl;
foo_2<int> (i12);
foo_2<int> (c22);
foo_2<char*> (i32);
foo_2<char*> (c42);

//==============================================
cout << endl;
cout << endl;
cout << "###### foo_all : template (usual) function with all arguments
######" << endl;
cout << " All template types are explicit" << endl;
foo_all<int, int> (i11, i12);
foo_all<int, char*> (i21, c22);
foo_all<char*, int> (c31, i32);
foo_all<char*, char*> (c41, c42);

cout << endl;
cout << " First template type is explicit" << endl;
cout << " Second template type is implicit (defined according to the
arg2 type)" << endl;
foo_all<int> (i11, i12);
foo_all<int> (i21, c22);
foo_all<char*> (c31, i32);
foo_all<char*> (c41, c42);

cout << endl;
cout << " All template types are implicit (defined according to the
arguments types)" << endl;
foo_all (i11, i12);
foo_all (i21, c22);
foo_all (c31, i32);
foo_all (c41, c42);


//##############################################
//##############################################
cout << endl;
cout << endl;
cout << "###### object.Foo_no : template member function without
arguments ######" << endl;
cout << " All template types are explicit" << endl;
object.template Foo_no<int, int> ();
object.template Foo_no<int, char*> ();
object.template Foo_no<char*, int> ();
object.template Foo_no<char*, char*> ();

//============================================== cout << endl; cout <<
endl; cout << "###### object.Foo_1 : template member function only with
first argument ######" << endl; cout << " All template types are explicit"
<< endl; object.template Foo_1<int, int> (i11); object.template Foo_1<int,
char*> (i21); object.template Foo_1<char*, int> (c31); object.template
Foo_1<char*, char*> (c41);

//============================================== cout << endl; cout <<
endl; cout << "###### object.Foo_2 : template member function only with
second argument ######" << endl; cout << " All template types are explicit"
<< endl; object.template Foo_2<int, int> (i12); object.template Foo_2<int,
char*> (c22); object.template Foo_2<char*, int> (i32); object.template
Foo_2<char*, char*> (c42);

cout << endl;
cout << " First template type is explicit" << endl;
cout << " Second template type is implicit (defined according to the
arg2 type)" << endl;
object.template Foo_2<int> (i12);
object.template Foo_2<int> (c22);
object.template Foo_2<char*> (i31);
object.template Foo_2<char*> (c41);

//==============================================
cout << endl;
cout << endl;
cout << "###### object.Foo_all : template member function with all
arguments ######" << endl;
cout << " All template types are explicit" << endl;
object.template Foo_all<int, int> (i11, i12);
object.template Foo_all<int, char*> (i21, c22);
object.template Foo_all<char*, int> (c31, i32);
object.template Foo_all<char*, char*> (c41, c42);

cout << endl;
cout << " First template type is explicit" << endl;
cout << " Second template type is implicit (defined according to the
arg2 type)" << endl;
object.template Foo_all<int> (i11, i12);
object.template Foo_all<int> (i21, c22);
object.template Foo_all<char*> (c31, i32);
object.template Foo_all<char*> (c41, c42);

cout << endl;
cout << " All template types are implicit (defined according to the
arguments types)" << endl;
// ATTENTION! not object.template Foo_all (v1, v2), but object.Foo_all
(v1, v2)
object.Foo_all (i11, i12);
object.Foo_all (i21, c22);
object.Foo_all (c31, i32);
object.Foo_all (c41, c42);

//========================
return 0;
}


###################################################
############# 4. Compiler #########################
###################################################

g++ -v : gcc version egcs-2.91.57 19980901 (egcs-1.1 release)

###################################################
############# 5. Hardware #########################
###################################################

uname -a : SunOS tibamsun8 5.6 Generic_105181-09 sun4m sparc
SUNW,SPARCstation-5

###################################################
############# 6. Results of the running ##########
###################################################


###### foo_no : template (usual) function without arguments ######
All template types are explicit
void foo_no<int, int>() : No input parameters
void foo_no<int, char *>() : No input parameters
void foo_no<char *, int>() : No input parameters
void foo_no<char *, char *>() : No input parameters


###### foo_1 : template (usual) function only with first argument ######
All template types are explicit
void foo_1<int, int>(int &) : arg1 = 11
void foo_1<int, char *>(int &) : arg1 = 21
void foo_1<char *, int>(char *&) : arg1 = three_aaaaa
void foo_1<char *, char *>(char *&) : arg1 = four_aaaaa


###### foo_2 : template (usual) function only with second argument ######
All template types are explicit
void foo_2<int, int>(int &) : arg2 = 12
void foo_2<int, char *>(char *&) : arg2 = two_bbbbb
void foo_2<char *, int>(int &) : arg2 = 32
void foo_2<char *, char *>(char *&) : arg2 = four_bbbbb

First template type is explicit
Second template type is implicit (defined according to the arg2 type)
void foo_2<int, int>(int &) : arg2 = 12
void foo_2<int, char *>(char *&) : arg2 = two_bbbbb
void foo_2<char *, int>(int &) : arg2 = 32
void foo_2<char *, char *>(char *&) : arg2 = four_bbbbb


###### foo_all : template (usual) function with all arguments ###### All
template types are explicit void foo_all<int, int>(int &, int &) : arg1 =
11, arg2 = 12 void foo_all<int, char *>(int &, char *&) : arg1 = 21, arg2
= two_bbbbb void foo_all<char *, int>(char *&, int &) : arg1 = three_aaaaa,
arg2 = 32 void foo_all<char *, char *>(char *&, char *&) : arg1 =
four_aaaaa, arg2 = four_bbbbb

First template type is explicit Second template type is implicit (defined
according to the arg2 type) void foo_all<int, int>(int &, int &) : arg1 =
11, arg2 = 12 void foo_all<int, char *>(int &, char *&) : arg1 = 21, arg2
= two_bbbbb void foo_all<char *, int>(char *&, int &) : arg1 = three_aaaaa,
arg2 = 32 void foo_all<char *, char *>(char *&, char *&) : arg1 =
four_aaaaa, arg2 = four_bbbbb

All template types are implicit (defined according to the arguments types)
void foo_all<int, int>(int &, int &) : arg1 = 11, arg2 = 12 void
foo_all<int, char *>(int &, char *&) : arg1 = 21, arg2 = two_bbbbb void
foo_all<char *, int>(char *&, int &) : arg1 = three_aaaaa, arg2 = 32 void
foo_all<char *, char *>(char *&, char *&) : arg1 = four_aaaaa, arg2 =
four_bbbbb


###### object.Foo_no : template member function without arguments ######
All template types are explicit
void MyClass::Foo_no<int, int>() : No input parameters
void MyClass::Foo_no<int, char *>() : No input parameters
void MyClass::Foo_no<char *, int>() : No input parameters
void MyClass::Foo_no<char *, char *>() : No input parameters


###### object.Foo_1 : template member function only with first argument ######
All template types are explicit
void MyClass::Foo_1<int, int>(int &) : Arg1 = 11
void MyClass::Foo_1<int, char *>(int &) : Arg1 = 21
void MyClass::Foo_1<char *, int>(char *&) : Arg1 = three_aaaaa
void MyClass::Foo_1<char *, char *>(char *&) : Arg1 = four_aaaaa


###### object.Foo_2 : template member function only with second argument
###### All template types are explicit void MyClass::Foo_2<int, int>(int &)
: Arg2 = 12 void MyClass::Foo_2<int, char *>(char *&) : Arg2 = two_bbbbb
void MyClass::Foo_2<char *, int>(int &) : Arg2 = 32 void MyClass::Foo_2<char
*, char *>(char *&) : Arg2 = four_bbbbb

First template type is explicit
Second template type is implicit (defined according to the arg2 type)
void MyClass::Foo_2<int, int>(int &) : Arg2 = 12
void MyClass::Foo_2<int, char *>(char *&) : Arg2 = two_bbbbb
void MyClass::Foo_2<char *, int>(int &) : Arg2 = 31
void MyClass::Foo_2<char *, char *>(char *&) : Arg2 = four_aaaaa


###### object.Foo_all : template member function with all arguments ######
All template types are explicit
void MyClass::Foo_all<int, int>(int &, int &) : Arg1 = 11, Arg2 = 12
void MyClass::Foo_all<int, char *>(int &, char *&) : Arg1 = 21, Arg2 =
two_bbbbb
void MyClass::Foo_all<char *, int>(char *&, int &) : Arg1 = three_aaaaa,
Arg2 = 32
void MyClass::Foo_all<char *, char *>(char *&, char *&) : Arg1 =
four_aaaaa, Arg2 = four_bbbbb

First template type is explicit
Second template type is implicit (defined according to the arg2 type)
void MyClass::Foo_all<int, int>(int &, int &) : Arg1 = 11, Arg2 = 12
void MyClass::Foo_all<int, char *>(int &, char *&) : Arg1 = 21, Arg2 =
two_bbbbb
void MyClass::Foo_all<char *, int>(char *&, int &) : Arg1 = three_aaaaa,
Arg2 = 32
void MyClass::Foo_all<char *, char *>(char *&, char *&) : Arg1 =
four_aaaaa, Arg2 = four_bbbbb

All template types are implicit (defined according to the arguments types)
void MyClass::Foo_all<int, int>(int &, int &) : Arg1 = 11, Arg2 = 12
void MyClass::Foo_all<int, char *>(int &, char *&) : Arg1 = 21, Arg2 =
two_bbbbb
void MyClass::Foo_all<char *, int>(char *&, int &) : Arg1 = three_aaaaa,
Arg2 = 32
void MyClass::Foo_all<char *, char *>(char *&, char *&) : Arg1 =
four_aaaaa, Arg2 = four_bbbbb
###################################################
############# END of INFORMATION #################
###################################################

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Alex Vinokur

unread,
Feb 14, 1999, 3:00:00 AM2/14/99
to
In article <01be5608$9794efc0$15dc...@mentor.magnet.at>,
"Alfred Kellner" <alfke...@magnet.at> wrote:
> Alex Vinokur <alexande...@telrad.co.il> wrote

> > "T.Yoshida" <yosh...@giw.khi.co.jp> wrote:
> > > Given the following two function templates:
> > >
> > > template < class T1, class T2 > int f( T2 ); // #1
> > > template < class T2 > int f( T2 ); // #2
> > >
> > > how the function call below is to be resolved?
> > >
> > > f<float>( 1.0F );
> > >
> > > (1) f<float,float>(float)
> > > (2) f<float>(float)
> > > (3) Ambiguous
> > [snip]
> [...]

> > template <typename T1, typename T2> void foo_2(T2 &second)
> > { /***/ }
> [...]

> > foo_2<int> (i12);
> > foo_2<int> (c22);
> > foo_2<char*> (i32);
> > foo_2<char*> (c42);
> [...]
> What I miss from your sample-code, is the definition of //#2
> template <typename T> void foo_2( T& ); //#2a
> which creates the overload-situation in question.

You are right.
Thank you.
>
> From the current C++-Standard, I couldn't find any part
> (expected somewhere in 14.5.5.2 Partial ordering of
> function templates) that gives an answer.
> This means the behaviour is unspecified.
>
> However, egcs-1.1.1 resolves the call in presence of #2a
> foo_2<int>(i11); --> foo_2<int,int>(int &);// arg=T2 !!
> with the 2nd _not_choosen_ possible call to
> foo_2<int>(int &);
> and _no_ ambiguity diagnosed.
>
> Egcs seems to think foo_2<int,int> is more specialized
> than foo_2<int>, what's a reasonable choice,
> but common sense will be surprised.
>
> --ALfred
>
> [ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
> [ about comp.lang.c++.moderated. First time posters: do this! ]
>

I would like to accentuate the importance of this problem on the following
example.

Alex

###################################################
############# 1. jp2_class.H ######################
###################################################


#include <string>

//############################################
// template (usual) function : one template-type; 2) with argument
template <typename T1>
void foo_1(T1 &first)
{
cout << __PRETTY_FUNCTION__ << " \t: arg = " << first << endl;
}


//############################################
// template (usual) function : two template-types; 2) only with first argument


template <typename T1, typename T2>
void foo_1(T1 &first)
{
cout << __PRETTY_FUNCTION__ << " \t: arg1 = " << first << endl;
}

//############################################
// template (usual) function : one template-type; 2) with argument
template <typename T2>
void foo_2(T2 &second)
{
cout << __PRETTY_FUNCTION__ << " \t: arg = " << second << endl;
}

//############################################
// template (usual) function : one template-type; 2) with argument
template <typename T2>
void foo_2A(T2 &second)
{
cout << __PRETTY_FUNCTION__ << " \t: arg = " << second << endl;
}

//############################################ // template (usual) function :
two template-types; 2) only with second argument template <typename T1,


typename T2> void foo_2(T2 &second) { cout << __PRETTY_FUNCTION__ << " \t:
arg2 = " << second << endl; }

###################################################
############# 2. jp2_class.cpp ####################
###################################################

#include "jp2_class.H"


// The file has no implementation (in this example)

###################################################
############# 3. jp2_main.C #######################
###################################################

#include "jp2_class.H"
int main ()
{


int i11 = 11;
int i12 = 12;
int i21 = 21;

int i32 = 32;

char* c21 = "two_aaaaa";
char* c22 = "two_bbbbb";
char* c31 = "three_aaaaa";

char* c41 = "four_aaaaa";
char* c42 = "four_bbbbb";


//##############################################
//##############################################


//==============================================
cout << endl;
cout << endl;

cout << "#############################" << endl;
cout << "###### foo_1 functions ######" << endl;
cout << "#############################" << endl;
cout << "###### foo_1<T1, T2> (T1& arg) ######" << endl;
cout << "====== All template types are explicit" << endl;


foo_1<int, int> (i11);
foo_1<int, char*> (i21);
foo_1<char*, int> (c31);
foo_1<char*, char*> (c41);

//==============================================
cout << endl;
cout << endl;

cout << "###### foo_1<T> (T& arg) ######" << endl;
cout << "====== The template type is explicit" << endl;
foo_1<int> (i11);
foo_1<char*> (c21);


//==============================================
cout << endl;
cout << "====== The template type is implicit" << endl;
foo_1 (i11);
foo_1 (c21);


//==============================================
cout << endl;
cout << endl;

cout << "#############################" << endl;
cout << "###### foo_2 functions ######" << endl;
cout << "#############################" << endl;
cout << "###### foo_2<T1, T2> (T2& arg) ######" << endl;
cout << "====== All template types are explicit" << endl;


foo_2<int, int> (i12);
foo_2<int, char*> (c22);
foo_2<char*, int> (i32);
foo_2<char*, char*> (c42);

cout << endl;
cout << "====== First template type is explicit" << endl;
cout << "====== Second template type is implicit (defined according to


the arg2 type)" << endl;
foo_2<int> (i12);
foo_2<int> (c22);
foo_2<char*> (i32);
foo_2<char*> (c42);


//============================================== cout << endl; cout <<
endl; cout << "###### foo_2<T> (T& arg) ######" << endl; cout << "======
The template type is explicit" << endl; foo_2<int> (i12); foo_2<int> (c22);
foo_2<char*> (i32); foo_2<char*> (c42); cout << "------ CONCLUSION : This
is not the foo_2<T> (T& arg) function" << endl; cout << "------ : This is
foo_2<T1, T2> (T2& arg) function" << endl;


//============================================== cout << endl; cout <<
"====== The template type is implicit" << endl; foo_2 (i11); foo_2 (c21);
cout << "------ CONCLUSION : This is the foo_2<T> (T& arg) function" << endl;


//============================================== cout << endl; cout <<
endl; cout << "###### foo_2A<T> (T& arg) ######" << endl; cout << "======
The template type is explicit" << endl; foo_2A<int> (i12); foo_2A<char*>
(c22); cout << "------ CONCLUSION : This is the foo_2A<T> (T& arg) function"
<< endl;


//============================================== cout << endl; cout <<
"====== The template type is implicit" << endl; foo_2A (i11); foo_2A (c21);
cout << "------ CONCLUSION : This is the foo_2A<T> (T& arg) function" <<
endl;


//==============================================
//========================
return 0;
}

###################################################
############# 4. Compiler #########################
###################################################

g++ -v : gcc version egcs-2.91.57 19980901 (egcs-1.1 release)

###################################################
############# 5. Hardware #########################
###################################################

uname -a : SunOS tibamsun8 5.6 Generic_105181-09 sun4m sparc
SUNW,SPARCstation-5

###################################################
############# 6. Results of the running ##########
###################################################

#############################
###### foo_1 functions ######
#############################
###### foo_1<T1, T2> (T1& arg) ######
====== All template types are explicit


void foo_1<int, int>(int &) : arg1 = 11
void foo_1<int, char *>(int &) : arg1 = 21
void foo_1<char *, int>(char *&) : arg1 = three_aaaaa
void foo_1<char *, char *>(char *&) : arg1 = four_aaaaa


###### foo_1<T> (T& arg) ######
====== The template type is explicit
void foo_1<int>(int &) : arg = 11
void foo_1<char *>(char *&) : arg = two_aaaaa

====== The template type is implicit
void foo_1<int>(int &) : arg = 11
void foo_1<char *>(char *&) : arg = two_aaaaa


#############################
###### foo_2 functions ######
#############################
###### foo_2<T1, T2> (T2& arg) ######
====== All template types are explicit


void foo_2<int, int>(int &) : arg2 = 12
void foo_2<int, char *>(char *&) : arg2 = two_bbbbb
void foo_2<char *, int>(int &) : arg2 = 32
void foo_2<char *, char *>(char *&) : arg2 = four_bbbbb

====== First template type is explicit
====== Second template type is implicit (defined according to the arg2 type)


void foo_2<int, int>(int &) : arg2 = 12
void foo_2<int, char *>(char *&) : arg2 = two_bbbbb
void foo_2<char *, int>(int &) : arg2 = 32
void foo_2<char *, char *>(char *&) : arg2 = four_bbbbb


###### foo_2<T> (T& arg) ######
====== The template type is explicit


void foo_2<int, int>(int &) : arg2 = 12
void foo_2<int, char *>(char *&) : arg2 = two_bbbbb
void foo_2<char *, int>(int &) : arg2 = 32
void foo_2<char *, char *>(char *&) : arg2 = four_bbbbb

------ CONCLUSION : This is not the foo_2<T> (T& arg) function
------ : This is foo_2<T1, T2> (T2& arg) function

====== The template type is implicit
void foo_2<int>(int &) : arg = 11
void foo_2<char *>(char *&) : arg = two_aaaaa
------ CONCLUSION : This is the foo_2<T> (T& arg) function


###### foo_2A<T> (T& arg) ######
====== The template type is explicit
void foo_2A<int>(int &) : arg = 12
void foo_2A<char *>(char *&) : arg = two_bbbbb
------ CONCLUSION : This is the foo_2A<T> (T& arg) function

====== The template type is implicit
void foo_2A<int>(int &) : arg = 11
void foo_2A<char *>(char *&) : arg = two_aaaaa
------ CONCLUSION : This is the foo_2A<T> (T& arg) function


###################################################
############# 7. Local Conclusions ################
###################################################

1. Two foo_1 (...) functions.
The functions template resolution is always specified & expected.

2. Two foo_2 (...) functions.
2.1) The functions template resolution is specified & expected
when using implicit template types (if it is possible).
^^^^^^^^
2.2) The foo_2<T1, T2> (T2& arg) function template resolution
is specified & expected
when using explicit template types.
^^^^^^^^
2.3) The foo_2<T> (T& arg) function template resolution
is impossible (as foo_2<T> (T& arg) function)
when using explicit template types.
^^^^^^^^
Note. The compiler resolves this
as foo_2<T1, T2> (T2& arg) function.

3. One foo_2A (...) function.
The function template resolution is always specified & expected.


###################################################
############# 8. Common Conclusions ###############
###################################################

1. Using the explicit template types
can cause unexpected resolution of function template.

2. Using the implicit template types (when it is possible)
always causes expected resolution of function template.


###################################################
############# 9. Question #########################
###################################################

1. Is the compiler behavior compiler-depended?
2. Is the compiler behavior planned?

0 new messages