Calling a template function from another template

P

Plissken.s

I have a template function which print out the content of a list: The
following compiles:
void PrintInt2 (int i) {
cout << i << " ";
}



template <class T>
void printList(T& list) {
// this compiles.
// for_each( list.begin(), list.end(), ptr_fun(&PrintInt2));
// this does not.
for_each( list.begin(), list.end(), ptr_fun(&Print));
}

But if i want to change the function PrintInt2 to a template function,
template <class T>
void Print(T item) {
cout << item << " ";
}
it does not compile. Can you please tell me how to make this line
compile?
// this does not.
for_each( list.begin(), list.end(), ptr_fun(&Print));

Thank you.
 
V

Victor Bazarov

I have a template function which print out the content of a list: The
following compiles:
void PrintInt2 (int i) {
cout << i << " ";
}



template <class T>
void printList(T& list) {
// this compiles.
// for_each( list.begin(), list.end(), ptr_fun(&PrintInt2));
// this does not.
for_each( list.begin(), list.end(), ptr_fun(&Print));
}

But if i want to change the function PrintInt2 to a template function,
template <class T>
void Print(T item) {
cout << item << " ";
}
it does not compile. Can you please tell me how to make this line
compile?
// this does not.
for_each( list.begin(), list.end(), ptr_fun(&Print));

I am guessing, but shouldn't it be 'ptr_fun(Print<T>)'? If it doesn't
help, follow the recommendations of FAQ 5.8.

V
 
E

eiji

template <typename T>
void Print(T item) {
std::cout << item << " ";
}

template <typename T1,typename T2>
void printList(T1& list) {
for_each( list.begin(), list.end(), &Print<T2>);
}

int main(int argc, char* argv[])
{
std::vector<double> t(10,3.0);
printList<std::vector<double>, double >(t);
return 0;
}

This is a fast solution!
Print and PrintList doesn't have the same template-prameter!

There are a couple of nice other solution!
 
P

Plissken.s

Thank you for your suggestion.

I change to this:
template <typename T>
void Print(T item) {
std::cout << item << " ";

}

template <typename T>
void printList(T& list) {
for_each( list.begin(), list.end(), ptr_fun(Print<T>));

}
And in my code, I call pritnList like this:
vector<float> a;
a.push_back(1.2);
a.push_back(3.2);
printList(a);

And I have these compile errors:
.../Utils.h:35: error: no match for 'operator<<' in 'std::cout <<
item'
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:67:
note: candidates are: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT,
_Traits>::eek:perator<<(std::basic_ostream<_CharT, _Traits>&
(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits
= std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:78:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(std::basic_ios<_CharT,
_Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char,
_Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:90:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(std::ios_base&
(*)(std::ios_base&)) [with _CharT = char, _Traits =
std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:125:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(long int) [with _CharT
= char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:159:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(long unsigned int)
[with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:102:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(bool) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:176:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(short int) [with _CharT
= char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:187:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(short unsigned int)
[with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:191:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(int) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:202:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(unsigned int) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:183:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(long long int) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:218:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(long long unsigned int)
[with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:242:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(double) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:217:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(float) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:265:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(long double) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:288:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(const void*) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:311:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT,
_Traits>::eek:perator<<(std::basic_streambuf<_CharT, _Traits>*) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:502:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, const unsigned
char*) [with _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:497:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, const signed char*)
[with _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:616:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, const char*) [with
_Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:571:
note: std::basic_ostream<_CharT, _Traits>&
std::eek:perator<<(std::basic_ostream<_CharT, _Traits>&, const char*)
[with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:463:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, unsigned char)
[with _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:458:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, signed char) [with
_Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/ostream.tcc:509:
note: std::basic_ostream<char, _Traits>&
std::eek:perator<<(std::basic_ostream<char, _Traits>&, char) [with _Traits
= std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/ostream:447:
note: std::basic_ostream<_CharT, _Traits>&
std::eek:perator<<(std::basic_ostream<_CharT, _Traits>&, char) [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/stl_algo.h:
In function '_Function std::for_each(_InputIterator, _InputIterator,
_Function) [with _InputIterator = __gnu_cxx::__normal_iterator<float*,
_Function = said:
, void>]':
.../Utils.h:41: instantiated from 'void printList(T&) [with T =
std::vector<float, std::allocator<float> >]'
.../BlockList.cpp:444: instantiated from here
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/stl_algo.h:158:
error: no match for call to
'(std::pointer_to_unary_function<std::vector<float,
std::allocator<float> >, void>) (float&)'
/usr/lib/gcc/i386-redhat-linux/4.0.2/../../../../include/c++/4.0.2/bits/stl_function.h:493:
note: candidates are: _Result std::pointer_to_unary_function<_Arg,
_Result>::eek:perator()(_Arg) const [with _Arg = std::vector<float,
std::allocator<float> >, _Result = void]
 
T

TB

(e-mail address removed) skrev:
Thank you for your suggestion.

I change to this:
template <typename T>
void Print(T item) {
std::cout << item << " ";

}

template <typename T>
void printList(T& list) {
for_each( list.begin(), list.end(), ptr_fun(Print<T>));

When you call printList with a container you need to supply the right
type to Print<>:

for_each( list.begin(), list.end(),
ptr_fun(Print said:
}
And in my code, I call pritnList like this:
vector<float> a;
a.push_back(1.2);
a.push_back(3.2);
printList(a);

And I have these compile errors:

<autosnipping huge amount of error messages>
 
V

Victor Bazarov

Thank you for your suggestion.

I change to this:
template <typename T>
void Print(T item) {
std::cout << item << " ";

}

template <typename T>
void printList(T& list) {
for_each( list.begin(), list.end(), ptr_fun(Print<T>));

Since you're calling 'printList' for a 'vector<float>', your 'T' is
'vector<float>'. If you want to use 'Print<float>', then you need
to replace "Print said:
}
And in my code, I call pritnList like this:
vector<float> a;
a.push_back(1.2);
a.push_back(3.2);
printList(a);
[..]

V
 
P

Plissken.s

Thanks. That works.

I have one related question, how can I pass an argument to this
template:
I change my code to this:
template <class T>
void print2(T item, ostream& os) {
os << item << " ";

}
template <class T>
void printList2(T& list, ostream& os) {
for_each( list.begin(), list.end(), ptr_fun(print2< typename
T::value_type>(os) ));

}

but I have a compile error:
.../Utils.h: In function 'void printList2(T&, std::eek:stream&) [with T =
std::vector<int, std::allocator<int> >]':
.../XWidthBlockMap.cpp:111: instantiated from here
.../Utils.h:73: error: no matching function for call to
'print2(std::basic_ostream<char, std::char_traits<char> >&)'
 
V

Victor Bazarov

I have one related question, how can I pass an argument to this
template:
I change my code to this:
template <class T>
void print2(T item, ostream& os) {
os << item << " ";

}
template <class T>
void printList2(T& list, ostream& os) {
for_each( list.begin(), list.end(), ptr_fun(print2< typename
T::value_type>(os) ));

the last argument in 'for_each' is an attempt to get 'ptr_fun' from
a function call:

ptr_fun( print2<blah>(os) )

Here, "print2<blah>(os)" is a function call. You probably want to define
your own functor (since 'bind2nd' isn't going to work) to pass 'os' to the
function _every_ time 'for_each' calls your functor. It would look
something like

struct my_print2 {
ostream& os;
my_print2(ostream& os) : os(os) {}
template<class T> void operator()(T t) {
print2(t, os);
}
};

and pass an instantiation of that functor to the 'for_each' instead of
'ptr_fun'.
}

but I have a compile error:
../Utils.h: In function 'void printList2(T&, std::eek:stream&) [with T =
std::vector<int, std::allocator<int> >]':
../XWidthBlockMap.cpp:111: instantiated from here
../Utils.h:73: error: no matching function for call to
'print2(std::basic_ostream<char, std::char_traits<char> >&)'

You're trying to call a function that doesn't exist.

V
 
T

TB

(e-mail address removed) skrev:
Thanks. That works.

I have one related question, how can I pass an argument to this
template:
I change my code to this:
template <class T>
void print2(T item, ostream& os) {
os << item << " ";

}

It takes two arguments now, not one.
template <class T>
void printList2(T& list, ostream& os) {
for_each( list.begin(), list.end(), ptr_fun(print2< typename
T::value_type>(os) ));

}

That will not compile.
but I have a compile error:
../Utils.h: In function 'void printList2(T&, std::eek:stream&) [with T =
std::vector<int, std::allocator<int> >]':
../XWidthBlockMap.cpp:111: instantiated from here
../Utils.h:73: error: no matching function for call to
'print2(std::basic_ostream<char, std::char_traits<char> >&)'

Learn to read error messages, it's a valuable human trait.

If you really want to learn how this all works, then I recommend
buying a copy of Josuttis' The C++ Standard Library.

Here's one solution:

template<typename T>
struct print : public std::unary_function<T,void> {
void operator()(T item) {
d_os << item << " ";
}
std::eek:stream & d_os;
print(std::eek:stream & os) : d_os(os) {}
};

template<typename T>
void printList(T const & list, std::eek:stream & os) {
std::for_each(list.begin(), list.end(), print<T::value_type>(os));
}
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top