question on function template

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

consider the following program:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <list>

using namespace std;

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;
}

template<typename T> void g(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;
}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

g(vi);

vector<long double> vld;
g(vld);

return EXIT_SUCCESS;
}

When fn() is called with 'vi' and 'ls', the parameter types deduced
for 'T' in fn() are 'vector<int>' and 'list<string>' respectively -
that is 'vector<int>' and 'list<string>' get substituted for 'T' in
fn(). However, when g() is called with 'vi' and 'vld', the parameter
types deduced for 'T' in g() are 'int' and 'long double' respectively
- that is, 'vector<int>' and 'vector<long double>' are NOT substituted
for 'T' in g().

I thought when g() is called with 'vi' ie 'g(vi)' would instantiate
void g(const vector< vector<int> > &arg) and when g() is called with
'vld' ie 'g(vld)' would instantiate void g(const vector< vector<long
double> > & arg). But it doesn't seem to be the case.

I am unable to understand the difference between the function template
argument deduction for fn() and g(). Kindly explain.

Thanks
V.Subramanian
 
I

Ian Collins

consider the following program:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <list>

using namespace std;

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;
}

template<typename T> void g(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;
}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

g(vi);

vector<long double> vld;
g(vld);

return EXIT_SUCCESS;
}

When fn() is called with 'vi' and 'ls', the parameter types deduced
for 'T' in fn() are 'vector<int>' and 'list<string>' respectively -
that is 'vector<int>' and 'list<string>' get substituted for 'T' in
fn(). However, when g() is called with 'vi' and 'vld', the parameter
types deduced for 'T' in g() are 'int' and 'long double' respectively
- that is, 'vector<int>' and 'vector<long double>' are NOT substituted
for 'T' in g().
Why should they? You have declared g with a parameter of const
std::vector<T>& and you have passed a std::vector<int> and a
std::vector<long double>, so T is int and long double.
 
D

diligent.snail

consider the following program:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <list>

using namespace std;

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;

}

template<typename T> void g(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;

}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

g(vi);

vector<long double> vld;
g(vld);

return EXIT_SUCCESS;

}

When fn() is called with 'vi' and 'ls', the parameter types deduced
for 'T' in fn() are 'vector<int>' and 'list<string>' respectively -
that is 'vector<int>' and 'list<string>' get substituted for 'T' in
fn(). However, when g() is called with 'vi' and 'vld', the parameter
types deduced for 'T' in g() are 'int' and 'long double' respectively
- that is, 'vector<int>' and 'vector<long double>' are NOT substituted
for 'T' in g().

I thought when g() is called with 'vi' ie 'g(vi)' would instantiate
void g(const vector< vector<int> > &arg) and when g() is called with
'vld' ie 'g(vld)' would instantiate void g(const vector< vector<long
double> > & arg). But it doesn't seem to be the case.

I am unable to understand the difference between the function template
argument deduction for fn() and g(). Kindly explain.

Thanks
V.Subramanian



In order to obtain the instantiation you expected, you should have
done:


vector< vector<long double> > vvld;
g( vvld );

in that case, T would be vector<long double>

Regards.
 
S

Salt_Peter

consider the following program:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <list>

using namespace std;

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;

}

template<typename T> void g(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;

}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

g(vi);

vector<long double> vld;
g(vld);

return EXIT_SUCCESS;

}

When fn() is called with 'vi' and 'ls', the parameter types deduced
for 'T' in fn() are 'vector<int>' and 'list<string>' respectively -
that is 'vector<int>' and 'list<string>' get substituted for 'T' in
fn(). However, when g() is called with 'vi' and 'vld', the parameter
types deduced for 'T' in g() are 'int' and 'long double' respectively
- that is, 'vector<int>' and 'vector<long double>' are NOT substituted
for 'T' in g().

I thought when g() is called with 'vi' ie 'g(vi)' would instantiate
void g(const vector< vector<int> > &arg) and when g() is called with
'vld' ie 'g(vld)' would instantiate void g(const vector< vector<long
double> > & arg). But it doesn't seem to be the case.

The parameters of a function call are not transposed, injected or
substituted into a templated function in any way.
In fact, the templated function is not generated unless its
typename(s) can be deduced in such a way as to *match* the signature
of a function call. Thats how one templated function can generate
countless specialized versions of itself.
You only get it if you use it.

g(vi) in the above code has an function-identifier g with a parameter
of type std::vector< int >.
That information is all that is used to attempt a function call/match
- possibly through deducing a type to fit the template and therefore
generate a concrete specialisation of the function template. The
return type is ignored (void in this case) since the return type is
never part of a function signature.

As an example, this could work:

template< typename T >
void h(const std::vector< std::vector< T > >& arg)
{
}

// problem is that that templated functions are not generated at all
at this point.

std::vector< std::vector< int > > vvn;
h(vvn); // ah !

// now that templated function can be generate for you.
// We have a deduceable type (int) that would provide a match
 
D

Daniel T.

consider the following program:

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <list>

using namespace std;

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;
}

template<typename T> void g(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;
}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

g(vi);

vector<long double> vld;
g(vld);

return EXIT_SUCCESS;
}

When fn() is called with 'vi' and 'ls', the parameter types deduced
for 'T' in fn() are 'vector<int>' and 'list<string>' respectively -
that is 'vector<int>' and 'list<string>' get substituted for 'T' in
fn(). However, when g() is called with 'vi' and 'vld', the parameter
types deduced for 'T' in g() are 'int' and 'long double' respectively
- that is, 'vector<int>' and 'vector<long double>' are NOT substituted
for 'T' in g().

I thought when g() is called with 'vi' ie 'g(vi)' would instantiate
void g(const vector< vector<int> > &arg) and when g() is called with
'vld' ie 'g(vld)' would instantiate void g(const vector< vector<long
double> > & arg). But it doesn't seem to be the case.

I am unable to understand the difference between the function template
argument deduction for fn() and g(). Kindly explain.

I don't see where your issue has been adequately explained, and frankly
I'm not sure what the explanation is.

I suspect that the compiler tries to match the parameter as best as
possible before making any substitutions. Note, for example, what the
compiler does if you make both function names the same...

template<typename T> void fn(T const & arg)
{
cout << "from fn: " << sizeof(arg) << endl;
return;
}

template<typename T> void fn(const vector<T>& arg)
{
cout << "from g: " << sizeof(T) << " "
<< sizeof(arg) << endl;
return;
}

int main()
{
vector<int> vi;
fn(vi);

list<string> ls;
fn(ls);

fn(vi);

vector<long double> vld;
fn(vld);

return EXIT_SUCCESS;
}

In this case, the second function is called for any vector. The first
function is only called if the parameter is not a vector.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top