Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Nested template specialization

3 views
Skip to first unread message

Sam

unread,
Jan 24, 2010, 9:52:49 PM1/24/10
to
I've been trying to figure out how to take a class template that takes one
template class parameter, that defines an inner member template class, that
also one class parameter; then specialization the inner member template
class whose template class parameter is the same as the outer template
class's class parameter.

After failing to figure out how to do it directly, I came up with a
circuitous workaround, but can't help but to think that there has to be a
better way. But first, here's what I started with:

template<typename outer_type>
class Outer {

public:

template<typename inner_type>
class Inner {

// …
};

// …
};

So, I'm trying to figure out how to define a specialization for
Inner<outer_type>. That is, a specialization for Inner with the same
typename as its Outer's typename. That is, a specialization for
Outer<int>::Inner<int>, Outer<classname>::Inner<classname>, etc…

g++ appears to compile the following syntax:

template<>
template<typename common_type>
class Outer<common_type>::Inner<common_type> {

// …
};

Yet, it didn't work for me. The following complete example results in the
generic template getting instantiated, and the same output from both
typeid::name() going to std::cout:

==========================================================================

#include <iostream>
#include <typeinfo>

template<typename outer_type>
class Outer {

public:

template<typename inner_type>
class Inner {

public:
Inner()
{
std::cout << "Generic template"
<< std::endl;
std::cout << typeid(outer_type).name() << std::endl;
std::cout << typeid(inner_type).name() << std::endl;
}

~Inner()
{
}
};
};

template<>
template<typename common_type>
class Outer<common_type>::Inner<common_type> {
public:
Inner()
{
std::cout << "Specialized" << std::endl;
}

~Inner()
{
}
};

class C {
};

int main()
{
Outer<C>::Inner<C> n;
}

==========================================================================

So, after beating my head against the wall, I finally came up with the
following solution that solves my immediate problem:

===========================================================================

#include <iostream>
#include <typeinfo>

template<typename outer_type,
typename inner_type> class OuterInner {

public:
OuterInner()
{
std::cout << "Generic template"
<< std::endl;
std::cout << typeid(outer_type).name() << std::endl;
std::cout << typeid(inner_type).name() << std::endl;
}

~OuterInner()
{
}
};

template<>
template<typename common_type>
class OuterInner<common_type, common_type> {
public:
OuterInner()
{
std::cout << "Specialized" << std::endl;
}

~OuterInner()
{
}
};

template<typename outer_type>
class Outer {

public:

template<typename inner_type>
class Inner : public OuterInner<outer_type, inner_type> {

public:
Inner()
{
}

~Inner()
{
}
};
};

class C {
};

int main()
{
Outer<C>::Inner<C> n;
}

===========================================================================

I'd really like to get rid of this extra inheritance, since it complicates
my overall class structure (the above is a minimalized example), and this
means that I'll have to start friending a bunch of stuff, which I'd rather
avoid doing.

0 new messages