Determine equality of template parameters?

J

Joseph Turian

Let's say I have a function template as follows:

template<class T, class U>
foo {
...
}

However, I'd like to have different behavior if T == U.
How can I check that?


Will it work as desired if I add the following specialization?

template<class T, class T>
foo {
...
}

Thanks,
Joseph
 
R

red floyd

Joseph said:
Let's say I have a function template as follows:

template<class T, class U>
foo {
...
}
I'm assuming this is a class template.
However, I'd like to have different behavior if T == U.
How can I check that?


Will it work as desired if I add the following specialization?

template<class T, class T>
foo {
...
}

template<class T>
class foo<T,T>
{
// ...
};
 
J

Joseph Turian

BTW, my original question still stands:

Does anyone know how to do template specialization in case the two
types are equal?

Here's what I'm trying to do:
If the two types are unequal, I convert from T to U before doing stuff
with the U items.
If the two types are equal, I want to save the conversion overhead.

Thanks

Joseph
 
B

benben

Joseph said:
No, function template.
Thanks anyway.

Joseph

template <typename T1, typename T2>
class same_types
{
public: enum {result = false};
};

template <typename T>
class same_types<T, T>
{
public: enum {result = true};
};

template<class T, class U>
void foo(void)
{
if (same_types<T, U>::result) // same types
{
// yada yada yada
}
else // different types
{
// blah blah blah
}
}


Regards,
Ben
 
V

Victor Bazarov

Joseph said:
Let's say I have a function template as follows:

template<class T, class U>

Missing the return value type here...
^
Missing argument list here...

Are you sure you were writing a _function_ template? You do
need some arguments.
However, I'd like to have different behavior if T == U.
How can I check that?

#include <iostream>
using namespace std;

template<class T, class U> struct same { enum { yes = 0 }; };
template<class T> struct same<T,T> { enum { yes = 1 }; };

template<class T, class U> void foo()
{
if (same<T,U>::yes)
cout << "foo<T,T>\n";
else
cout << "foo<T,U>\n";
}

int main(int argc,char *argv[])
{
foo<int,double>();
foo<double,int>();
foo<char,char>();
}

Will it work as desired if I add the following specialization?

template<class T, class T>

Missing the return value type here...

^
Missing argument list here...

No partial specialisations of funciton templates allowed. See
above.

V
 
B

benben

template said:
class same_types
{
public: enum {result = false};
};

template <typename T>
class same_types<T, T>
{
public: enum {result = true};
};

template<class T, class U>
void foo(void)
{
if (same_types<T, U>::result) // same types
{
// yada yada yada
}
else // different types
{
// blah blah blah
}
}

Alternatively, if RTTI is enabled on your implementation then simply:

template <typename T, typename U>
void foo(void)
{
if (typeid(T) == typeid(U))
{
// blah
}
else
{
// blah
}
}

With aggressive code optimization the two version should generate
identical code, although the first version is easier to optimize (but at
the same time more verbose.)

Regards,
ben
 
A

andy

Victor said:
template<class T, class U> struct same { enum { yes = 0 }; };
template<class T> struct same<T,T> { enum { yes = 1 }; };

[...]

Can use boost::is_same to save writing above and ...

.... Can use boost::enable_if to distinguish two functions based on
predicate:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>

using namespace std;

template<class T, class U>
typename boost::enable_if<
boost::is_same said:
foo()
{
cout << "foo<T,T>\n";
}

template<class T, class U>
typename boost::disable_if<
boost::is_same said:
foo()
{
cout << "foo<T,U>\n";
}

int main(int argc,char *argv[])
{
foo<int,double>();
foo<double,int>();
foo<char,char>();
}

BTW needs a reasonably good compiler though ;-)

regards
Andy Little
 
V

Victor Bazarov

Victor Bazarov wrote:

template<class T, class U> struct same { enum { yes = 0 }; };
template<class T> struct same<T,T> { enum { yes = 1 }; };


[...]

Can use boost::is_same to save writing above and ...

[...]

Why use a third-party library when it's possible without it?
 
A

andy

Victor said:
Victor Bazarov wrote:

template<class T, class U> struct same { enum { yes = 0 }; };
template<class T> struct same<T,T> { enum { yes = 1 }; };


[...]

Can use boost::is_same to save writing above and ...

[...]

Why use a third-party library when it's possible without it?

Simple. It follows a standard convention. Change name of yes member to
value and your version would work with enable_if, in version above,
however though it then works in that case, in the following example I
have modified the code so that I am selecting on condition that both T
and U are the same and both are pointers. Feel free to try
uncommenting the handrolled version with changed name and using that
instead. At this point its rather more work to keep redoing all the
metafunctions. Note also that both is_same and is_pointer are scheduled
to be included in the standard library in future. Use the standard
functions because they follow standard practise and everyone knows what
their exact layout syntax and purpose is. They've been tested and
debugged and will be more portable. IOW it saves time and effort all
round.

I'm sure you knew all that though. Just accept that my way is better
for once ;-)

cheers
Andy Little
------------------

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/mpl/and.hpp>

using namespace std;

/////////////////////////////
// hint: use value member so will work with enable_if
template<class T, class U> struct same { enum { value = 0 }; };
template<class T> struct same<T,T> { enum { value = 1 }; };
/////////////////////////////

template<class T, class U>
typename boost::enable_if<
boost::mpl::and_<
boost::is_same<T,U>,
// same said:
foo()
{
cout << "foo<T*,T*>\n";
}

template<class T, class U>
typename boost::disable_if<
boost::mpl::and_<
boost::is_same<T,U>,
// same said:
foo()
{
cout << "foo<T,U>\n";
}

int main(int argc,char *argv[])
{
foo<int,double>();
foo<double,int>();
foo<char,char>();
foo<const char*,const char*>();
}
 
V

Victor Bazarov

Victor Bazarov wrote:

Victor Bazarov wrote:



template<class T, class U> struct same { enum { yes = 0 }; };
template<class T> struct same<T,T> { enum { yes = 1 }; };


[...]

Can use boost::is_same to save writing above and ...

[...]

Why use a third-party library when it's possible without it?


Simple. It follows a standard convention.

What standard convention? Please quote the Standard document that
explains your claim about the "convention".
> Change name of yes member to
value and your version would work with enable_if,

What 'enable_if'? There is no "enable_if" in the Standard.
> in version above,
however though it then works in that case, in the following example I
have modified the code so that I am selecting on condition that both T
and U are the same and both are pointers. Feel free to try
uncommenting the handrolled version with changed name and using that
instead. At this point its rather more work to keep redoing all the
metafunctions. Note also that both is_same and is_pointer are scheduled
to be included in the standard library in future. Use the standard
functions

Which part of Boost is standard at this point?
> because they follow standard practise and everyone knows what
their exact layout syntax and purpose is. They've been tested and
debugged and will be more portable. IOW it saves time and effort all
round.

I'm sure you knew all that though. Just accept that my way is better
for once ;-)

_What_ may be better? A third-party library? Yes, it may. But why
involve yourself with it if you don't have to?
cheers
Andy Little
------------------

V
 
A

andy

Victor said:
Andy Little wrote

What standard convention? Please quote the Standard document that
explains your claim about the "convention".

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf

see sections 4.3, 4.5.1 and 4.6.
What 'enable_if'? There is no "enable_if" in the Standard.

Where did I state that enable_if was in "The Standard"? enable_if is
part of the boost libraries. I thought that was clear from the
namespace prefix I gave it in the code example. Do you not know about
boost? Sorry for not spelling it out . See:

http://www.boost.org/libs/utility/enable_if.html

See http://www.boost.org for information about boost itself.
_What_ may be better? A third-party library? Yes, it may. But why
involve yourself with it if you don't have to?

I refer you to the answers I gave to this same question in my previous
post. I suggest you answer those points Before raising further
questions, else I will assume that you are being destructive and will
simply ignore any further contributions you make in this thread.

cheers
Andy Little
 
A

andy

Victor said:
This is not _the_Standard_. This is a _proposal_. I don't understand
why you keep missing my point. Read the beginning of the document itself
and get the paragraph 1/2 into your brain. Then we can talk.

Ok. I believe my use of the word standard has caused a
misunderstanding. I shall specifically say the C++ standard when I
mean to refer to that document otherwise I shall use the word standard
to mean common accepted use.

I'd also like to draw your attention to 1-3 in the document, which is
extremely relevant.


cheers
Andy Little
 
J

Joseph Turian

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/mpl/and.hpp>

Much as I hate to interrupt a good argument, I would like to say the
following:
I've begun learning about templates only recently and I was---a few
minutes ago---trying to figure out how to get boost to do these sorts
of things. I wasn't having much luck until I read the example code in
Andy's post, which I found most helpful. So thanks.


Joseph
 

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
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top