Douglas Edward
Douglas Edward

Reputation: 155

Class template specializing a method c++

Say I have a class template in which some methods are type specific.

template <typename T>
class Shape
{
...
void Foo();
...
};

Now I would specialize the type-specific functions using, for example:

void Shape<bool>::Foo() {...};
void Shape<double>::Foo() {...};

Question:

  1. What if Foo should have different parameters depending on the type? Is it possible to specialize a method for a specific type using parameters different from the ones in the class declaration? I suspect it's not allowed, so how should it be done?

  2. How to prevent class instantiation for types for which Foo hasn't been defined?

  3. When should virtual and pure virtual functions should be used in contrast to the siutation I have described? Is it possible to mix both templates and inheritance?

Upvotes: 1

Views: 683

Answers (2)

  • 1a . What if Foo should have different parameters depending on the type? Is it possible to specialize a method for a specific type using parameters different from the ones in the class declaration?

No. Yes, As pointed out by Nathan Monteleone below, this is possible by fully specializing the class Shape.

  • 1b . I suspect it's not allowed, so how should it be done?

Can you turn the function itself into a template independent of the class

class Shape {
    //...
    template <typename T>
    void Foo();
    //...
};
  • 2 . How to prevent class instantiation for types for which Foo hasn't been defined?

In the class body:

template<typename U> //note the different typename
class Shape {
    static_assert(std::is_same<U, bool>::value || std::is_same<U, double>::value, "Type forbidden");
    //...
    inline void Foo() {
        if( std::is_same<U, bool>::value ) Foo_impl_bool();
        else if( std::is_same<U, double>::value ) Foo_impl_double();// and so on.
        // this function is likely to get optimized since the conditionals are constexpr
    }
    private:
    void Foo_impl_bool();//...
};

3a . When should virtual and pure virtual functions should be used in contrast to the situation I have described?

The answers to 1b and 2 are 2 separate solutions, if neither of them is possible the other possibilities are:

  1. Extract that function into its own class.

  2. Use interface inheritance for this function alone.

3b . Is it possible to mix both templates and inheritance?

Yes

Upvotes: 1

Nathan Monteleone
Nathan Monteleone

Reputation: 5470

(1) Sort of, but not quite the way you're trying to do it. You basically want the specializations to define the function; it's quite a bit different from when you are declaring base and derived classes.

template <typename T> class Shape {
    static_assert(false, "Not implemented");
};

template <> class Shape<bool> {
    void Foo(bool a, std::string b) {...}
};

template <> class Shape<int> {
    void Foo(int, std::string, whatever else) {...}
};

Even if you were to define Foo in the original non-specialized Shape, it would have no effect on the specializations. Full specializations don't extend the original template, they replace it!

(2) Use static_assert. See the example above.

(3) Yes, you can mix templates and inheritence. Virtual functions runtime polymorphism and static polymorphism. Template parameters have to be known at compile time whereas the exact type of a runtime polymorphic object does not, because they can be referred to by a base class reference. In the templated example above you cannot simply say

template <class T> Shape {...};

...

Shape* myShape;   // Compiler error: Shape requires a template parameter

However with inheritence you can:

class ShapeBase { virtual void Foo() = 0; };
class Circle : public ShapeBase { virtual void Foo() { ... } };
class Square : public ShapeBase { virtual void Foo() { ... } };
...

Shape* myShape = new Circle;
myShape->Foo(); // calls Circle->Foo()

Note when you're working with inheritence, the function signatures DO have to match! That's the price you pay for deferring the decision till runtime.

Upvotes: 0

Related Questions