function template specialization

A

aaragon

Hi... after trying several things with some templated code I decided
to ask the experts a couple of things. I have the following class
template:

template<class A>
class Expr {
A a_;
public:
... // some public functions
...
friend inline std::eek:stream& operator<<(std::eek:stream& os, const
Expr<A>& e) {
os<<e.a_();
return os;
}
};

operator<< works just fine, but then I wanted to have the operator<<
with different behaviors depending on the template parameter. So, I
tried the following inside the class:
// declaration inside the class
friend std::eek:stream& operator<<<A>(std::eek:stream& os, const Expr&
e);

and defining the function outside:
template <class A>
inline std::eek:stream& operator<<(std::eek:stream& os, const Expr<A>&
e) {
os<<e();
return os;
}

Then I got just too many errors because of ambiguous calls and others
like:
cppblas.hpp:862: error: template-id 'operator<< <UnOp<Vector<double>,
TrOp> >' for 'std::basic_ostream<char, std::char_traits<char> >&
operator<<(std::basic_ostream<char, std::char_traits<char> >&, const
Expr<UnOp<Vector<double>, TrOp> >&)' does not match any template
declaration

So then, I decided to forward the function call to another function,
say print:

template <class A>
inline std::eek:stream& print(std::eek:stream& os, const Expr<A>& e) {
os<<e();
return os;
}

so this also works fine, and now I can specialize the function for
specific class of A:

template <>
inline std::eek:stream& print<someClass>(std::eek:stream& os, const
Expr<someClass>& e) {
// partially specialized for someClass
return os;
}

Now the questions is, is this the better way to do this? Forwarding a
function call seems right, but probably it can be done without another
function. I tried hard overloading operator<< but no success. Any
hints??

Thank you all...

 
I

Ian Collins

aaragon said:
Hi... after trying several things with some templated code I decided
to ask the experts a couple of things. I have the following class
template:

template<class A>
class Expr {
A a_;
public:
... // some public functions
...
friend inline std::eek:stream& operator<<(std::eek:stream& os, const
Expr<A>& e) {
os<<e.a_();

That line won't compile.
So then, I decided to forward the function call to another function,
say print:

template <class A>
inline std::eek:stream& print(std::eek:stream& os, const Expr<A>& e) {
os<<e();
return os;
}

so this also works fine, and now I can specialize the function for
specific class of A:

template <>
inline std::eek:stream& print<someClass>(std::eek:stream& os, const
Expr<someClass>& e) {
// partially specialized for someClass
return os;
}

Now the questions is, is this the better way to do this? Forwarding a
function call seems right, but probably it can be done without another
function. I tried hard overloading operator<< but no success. Any
hints??

You could make the outputting function a member of the class, say

std::eek:stream& output( std::eek:stream& os ) const
{
os << a_;
return os;
}

friend std::eek:stream& operator<<(std::eek:stream& os, const Expr& e)
{
return e.output( os );
}

and specialise output as required:

template <>
std::eek:stream& Expr<int>::eek:utput( std::eek:stream& os ) const
{
return os << "Boo!";
}
 
A

aaragon

That line won't compile.










You could make the outputting function a member of the class, say

std::eek:stream& output( std::eek:stream& os ) const
{
os << a_;
return os;
}

friend std::eek:stream& operator<<(std::eek:stream& os, const Expr& e)
{
return e.output( os );
}

and specialise output as required:

template <>
std::eek:stream& Expr<int>::eek:utput( std::eek:stream& os ) const
{
return os << "Boo!";

}

Thanks for the tip...
 
J

James Kanze

Hi... after trying several things with some templated code I
decided to ask the experts a couple of things. I have the
following class template:
template<class A>
class Expr {
A a_;
public:
... // some public functions
...
friend inline std::eek:stream& operator<<(std::eek:stream& os, const
Expr<A>& e) {
os<<e.a_();
return os;
}
};
operator<< works just fine,

But maybe not for the reason you think:).
but then I wanted to have the operator<< with different
behaviors depending on the template parameter. So, I tried the
following inside the class:
// declaration inside the class
friend std::eek:stream& operator<<<A>(std::eek:stream& os, const Expr&
e);
and defining the function outside:
template <class A>
inline std::eek:stream& operator<<(std::eek:stream& os, const Expr<A>&
e) {
os<<e();
return os;
}

In sum, you declare a non-template function as friend, and you
implement a function template. They're not the same thing.

They way I usually handle this is more or less what Ian
suggested: I define a member function which does the actual
work, and then invoke it in my operator<<. But it's possible to
declare function templates, or specializations of function
templates, as friends. Note however that to do so, it is
necessary to declare the function template before the class
template definition.
Then I got just too many errors because of ambiguous calls and
others like:
cppblas.hpp:862: error: template-id 'operator<< <UnOp<Vector<double>,
TrOp> >' for 'std::basic_ostream<char, std::char_traits<char> >&
operator<<(std::basic_ostream<char, std::char_traits<char> >&, const
Expr<UnOp<Vector<double>, TrOp> >&)' does not match any template
declaration
So then, I decided to forward the function call to another
function, say print:
template <class A>
inline std::eek:stream& print(std::eek:stream& os, const Expr<A>& e) {
os<<e();
return os;
}
so this also works fine, and now I can specialize the function
for specific class of A:
template <>
inline std::eek:stream& print<someClass>(std::eek:stream& os, const
Expr<someClass>& e) {
// partially specialized for someClass
return os;
}
Now the questions is, is this the better way to do this?

That's the way I do it.
Forwarding a function call seems right, but probably it can be
done without another function. I tried hard overloading
operator<< but no success. Any hints??

I'm not sure of the exact syntax, because I don't use it, but
you'd probably have to start with something like:

template < typename T >
class Expr ;

template< typename T >
std::eek:stream& operator<<( std::eek:stream&, Expr< T > const& ) ;

template< typename T >
class Expr
{
// ...
friend template<> std::eek:stream& operator<<(
std::eek:stream&, Expr< T > const7 ) ;
// (or something like that. As I said, I'm not too
// sure of the syntax.)
} ;
 
A

aaragon

But maybe not for the reason you think:).


In sum, you declare a non-template function as friend, and you
implement a function template. They're not the same thing.

They way I usually handle this is more or less what Ian
suggested: I define a member function which does the actual
work, and then invoke it in my operator<<. But it's possible to
declare function templates, or specializations of function
templates, as friends. Note however that to do so, it is
necessary to declare the function template before the class
template definition.




That's the way I do it.


I'm not sure of the exact syntax, because I don't use it, but
you'd probably have to start with something like:

template < typename T >
class Expr ;

template< typename T >
std::eek:stream& operator<<( std::eek:stream&, Expr< T > const& ) ;

template< typename T >
class Expr
{
// ...
friend template<> std::eek:stream& operator<<(
std::eek:stream&, Expr< T > const7 ) ;
// (or something like that. As I said, I'm not too
// sure of the syntax.)
} ;

--
James Kanze (GABI Software) email:[email protected]
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

Thanks James...
 

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

No members online now.

Forum statistics

Threads
473,965
Messages
2,570,148
Members
46,710
Latest member
FredricRen

Latest Threads

Top