5

EDIT: I didn't actually get a chance to test out any of the suggested solutions as I went on a vacation, and by the time I was back, the people responsible for the class template had made some changes that allowed me to get around the need to use types defined in the class template itself.

Thanks to everyone for their help though.


In a nutshell - and feel free to correct my wording, templates are still a bit of voodoo to me, - I need to know if I can use a (protected) struct or a #typedef defined inside a class template from my specialized class. For example:

This is the class template:

template<typename T>
class A : public C<T>
{
protected:
    struct a_struct { /* Class template implementation, doesn't depend on T */ };
    void foo( a_struct a );
};

Which I need to fully specialize for T = VAL:

template<>
class A< VAL > : public C< VAL >
{
    void foo( a_struct a )
    {
        // My implementation of foo, different from the class template's
    }
};

If I do something like this, however, the compiler complains that a_struct is undefined in my specialized class. I tried specializing and inheriting from the class template but that got... messy.

I saw some solutions, but all of them involved modifying the class template, which is something I am not able to easily do (different team).

Thoughts?

Argent
  • 725
  • 2
  • 7
  • 24
  • Look at one of the many other questions on SO where the need for `typename` in templates is explained: http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords – JSF Dec 22 '15 at 15:31
  • Sorry, I initially misunderstood your question. You don't want to inherit a type from the base class but rather from the unspecialized version of yourself. – JSF Dec 22 '15 at 15:37
  • I think you can create a fake base without "modifying" the original. Create a class inheriting from the original and friending the fake base, so the fake base can steal the type definition from the protected area of the original into its own protected area. Then use that fake base as the specialization's real base. – JSF Dec 22 '15 at 15:41

3 Answers3

4

No, you can't use members of the primary template declaration in your specialization of the class template. That is because in essence a template class specialization declares a completely new class template that is applied when the template arguments match the specialization.

You have two options available though, if you want to do something like in your example:

  • You can specialize the template class member function. This is useful if it is indeed only one member function that is special (or at least the number of member functions is limited).
  • You can bring the declaration of the member (-type) in a common base class.

Since you indicated in an edit that you can't change the class template itself, specializing the member function seems the best option.

A simplified example of specializing a member function only

template< class T>
class Printer
{
public:
    struct Guard {};
    void DoPrint( const T& val)
    {
        Guard g;
        (void)g;
        std::cout << val << '\n';
    }
};

struct Duck {};

template<>
void Printer<Duck>::DoPrint( const Duck& val)
{
    Guard g;
    (void)g;
    std::cout << "Some duck\n";
}

The Guard here is only used to demonstrate that this type is available to both the primary and the specialized implementation of DoPrint().

dhavenith
  • 1,958
  • 11
  • 13
1

It's not beautiful, but you can do it like this:

template<typename T>
class C
{

};

template<typename T>
class A : public C<T>
{
protected:
    friend A<int>;
  // ^^^^^^
    struct a_struct { /* Class template implementation, doesn't depend on T */ };
    void foo( a_struct a );
};

template<>
class A< int > : public C< int >
{
    using a_struct = typename A<void>::a_struct;
  // ^^^^^^
    void foo( a_struct a )
    {
        // My implementation of foo, different from the class template's
    }
};
Rabbid76
  • 142,694
  • 23
  • 71
  • 112
0

or how about, re-declaring struct a_struct in the specialized template, with same functionality as default one.

I know it may not sound good since you need to inject in all specialized templates. But that is one i can think of now.