By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,201 Members | 914 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,201 IT Pros & Developers. It's quick & easy.

specialization of a template function in a template class?!?!?

P: n/a
Just trying to learn some things about templates. Was wondering how
boost::tupple really works, but the headers were a bit confusing to me.
I know you get do something like the following, just want to know how
it works with the overloading of get<>().

boost::tupple<int,doubletup(1,2.0);

double d=tup.get<2>(); // equal 2.0

// simple set up,
template <class T1,class T2class MyPair
{
public:
T1* m_t1;
T2* m_t2;
MyPair(T1* t1,T2* t2)
: m_t1(t1), m_t2(t2)
{}

// want to know how to do this
template <int J T1* get() {return m_t1;}

// just wondering if I could do this
template <class J J* get() {return 0;}
};

// can I specialize this way?
template <class T1,class T2T1* MyPair<T1,T2>::get<1>() { return
m_t1;}
template <class T1,class T2T2* MyPair<T1,T2>::get<2>() { return
m_t2;}

// specialized this way??!?!?
template <class T1,class T2T1* MyPair<T1,T2>::get<T1>() { return
m_t1;}
template <class T1,class T2T2* MyPair<T1,T2>::get<T2>() { return
m_t2;}

thanks
-sal

Aug 3 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
po**************@yahoo.com wrote:
Just trying to learn some things about templates. Was wondering how
boost::tupple really works, but the headers were a bit confusing to me.
I know you get do something like the following, just want to know how
it works with the overloading of get<>().

boost::tupple<int,doubletup(1,2.0);

double d=tup.get<2>(); // equal 2.0

// simple set up,
template <class T1,class T2class MyPair
{
public:
T1* m_t1;
T2* m_t2;
MyPair(T1* t1,T2* t2)
: m_t1(t1), m_t2(t2)
{}

// want to know how to do this
template <int J T1* get() {return m_t1;}

// just wondering if I could do this
template <class J J* get() {return 0;}
};

// can I specialize this way?
template <class T1,class T2T1* MyPair<T1,T2>::get<1>() { return
m_t1;}
template <class T1,class T2T2* MyPair<T1,T2>::get<2>() { return
m_t2;}

// specialized this way??!?!?
template <class T1,class T2T1* MyPair<T1,T2>::get<T1>() { return
m_t1;}
template <class T1,class T2T2* MyPair<T1,T2>::get<T2>() { return
m_t2;}

thanks
-sal
I realize the nature of your question prevents posting compilable code,
but you should at least try to reduce the errors to the part you are
asking about. In particular, you need to include
<boost/tuple/tuple.hpp>, you need to spell tuple correctly (not
tupple), and get uses a zero based index, so you should be using get<1>
instead of get<2>.

Now, to answer your question, you cannot specialize a template unless
all enclosing templates are totally specialized. Why is this? Beats
me. I see no good reason for the restriction, but the standard doesn't
allow it. One thing you may try (a quick glance at tuple's
implementation suggests boost does something like this) is to create a
non-member template function, and forward calls to you member function
to the non-member version. Then specialize the non-member version
however you like.

Getting the correct return type for your get function can be tricky.
The best solution is to create some sort of metafunction that produces
the correct type for you.

There is another set of problems to deal with. Particularly, that a
function cannot be partially specialized (and you would like to
specialize it based on the types T1 and T2, as well as the return
type). So, instead of using a non-member function, it may be necessary
to use a static member of a separate class.

All put together, it is going to look something like this (I've removed
your second set of specializations. Consider them an exercise for the
reader.):

// Metafunction to help us get the return type.
template <int N, class T1, class T2>
struct ReturnTraits ;

template <class T1, class T2>
struct ReturnTraits<0, T1, T2>
{
typedef T1 ReturnType ;
} ;

template <class T1, class T2>
struct ReturnTraits<1, T1, T2>
{
typedef T2 ReturnType ;
} ;

// Helper to which we delegate calls to get to get around
specialization rules.
template <int N, class ReturnType, class PairTypestruct get_class ;

template <class ReturnType, class PairType>
struct get_class<0, ReturnType, PairType>
{
static ReturnType get(PairType & p)
{
p.m_t1 ;
}
} ;

template <class ReturnType, class PairType>
struct get_class<1, ReturnType, PairType>
{
static ReturnType get(PairType & p)
{
p.m_t2 ;
}
} ;

// simple set up,
template <class T1,class T2class MyPair
{
public:
T1* m_t1;
T2* m_t2;
MyPair(T1* t1,T2* t2)
: m_t1(t1), m_t2(t2)
{}

// want to know how to do this
template <int J>
typename ReturnTraits<J, T1, T2>::ReturnType * get()
{
return get_class<J, typename ReturnTraits<J, T1,
T2>::ReturnType,
MyPair<T1, T2::get();
}
};

--
Alan Johnson

Aug 3 '06 #2

P: n/a

Alan Johnson wrote:
po**************@yahoo.com wrote:
....

Thanks for the long answer Alan. FYI, didn't post boost code because I
know how to use tupple, I wanted to know how the templates worked so I
could try something similar here.

Anyway, thanks again for the in-depth answer. Going to take me a while
to digest it.

-sal

Aug 7 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.