Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Class Template's Internal Types from a Specialized Class

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?

like image 850
Argent Avatar asked Dec 22 '15 15:12

Argent


People also ask

What is the difference between generic class template and specialization template?

Key differences between generics and C++ templates: Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.

What is the difference between a class template and an ordinary class?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template.

Can class template be nested?

Member templates that are classes are referred to as nested class templates. Member templates that are functions are discussed in Member Function Templates. Nested class templates are declared as class templates inside the scope of the outer class. They can be defined inside or outside of the enclosing class.

What is the difference between class template and template class?

Template class : A class that has generic definition or a class with parameters which is not instantiated until the information is provided by the client. It is referred to a jargon for plain templates.


2 Answers

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().

like image 55
dhavenith Avatar answered Nov 23 '22 07:11

dhavenith


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
    }
};
like image 39
Rabbid76 Avatar answered Nov 23 '22 06:11

Rabbid76