koreus737
koreus737

Reputation: 671

How to write a derived class which specifies type parameters for a templated base

I'm learning C++ and I am having trouble bringing this design pattern over from C#. I can't work out if this pattern will not work in C++ or if I just have the incorrect syntax.

In the example I want to create a class that decodes a bitset.

In C# with generics it would look something like this :

abstract class Base<T>
{
  public abstract T GetValue(BitArray bits);
}

class Derived : Base<MyType>
{
  public override MyType GetValue(BitArray bits)
  {
    // Do some magic to decode this bitset
  }
}

This is my naive attempt in C++

template<T,Q> 
class Base
{
public:
    Base() = default;
    virtual ~Base() = 0;
    virtual T* GetValue(const std::bitset<Q>& bits) const = 0;
}

class Derived : Base<MyType, 32>
{
public:
    Derived();
    ~Derived();
    MyType* GetValue(const std::bitset<32>& bits) const;
}

MyType* Derived::GetValue(const std::bitset<32>)
{
    // Do some magic to decode this bitset
}

The compiler throws all manner of errors when I try to compile that C++ code (which I imagine is wrong in a number of ways).

How might I achieve this pattern of having the inheriting class specify a type parameter for the template of the base in C++?

Upvotes: 0

Views: 45

Answers (3)

Pavel P
Pavel P

Reputation: 16882

The compiler throws all manner of errors when I try to compile that C++ code (which I imagine is wrong in a number of ways).

  • missing semicolon after class declaration
  • wrong syntax in template declaration
  • missing includes for std::bitset
  • MyType is not defined
  • you shouldn't use public or protected inheritance from Base

More over, it's no clear why would you have that method virtual at all. You should also perhaps return by value from Derived::GetValue, or perhaps a smart pointer to MyType:

unique_ptr<MyType> Derived::GetValue(const std::bitset<32> &) {...}

Sample code:

#include <bitset>
#include <memory>

class MyType;

template<typename T, unsigned Q>
class Base
{
public:
    virtual std::unique_ptr<T> GetValue(const std::bitset<Q>& bits) const = 0;
};

class Derived : public Base<MyType, 32>
{
public:
    std::unique_ptr<MyType> GetValue(const std::bitset<32>& bits) const;
};

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123094

No offense, but your errors are just due to a couple of more or less obvious mistakes:

  • no ; after class declaration
  • missing definition of MyType
  • missing #incldue <bitset>
  • mismatch between declaration and definition of GetValue
  • missing typename for T
  • Q should be a size_t

Fixing those it compiles:

#include <iostream>
#include <bitset> //
using namespace std;

struct MyType{}; //

template<typename T,size_t Q>  //
class Base
{
public:
    Base() = default;
    virtual ~Base() = 0;
    virtual T* GetValue(const std::bitset<Q>& bits) const = 0;
}; //

class Derived : Base<MyType, 32>
{
public:
    Derived();
    ~Derived();
    MyType* GetValue(const std::bitset<32>& bits) const;
}; //

MyType* Derived::GetValue(const std::bitset<32>&) const //
{
    // Do some magic to decode this bitset
}


int main() {
    // your code goes here
    return 0;
}

Upvotes: 0

cdhowie
cdhowie

Reputation: 169281

You have multiple errors:

template<T,Q>                       // Wrong
template<typename T, std::size_t Q> // Fixed

MyType* Derived::GetValue(const std::bitset<32>)         // Wrong
MyType* Derived::GetValue(const std::bitset<32> &) const // Fixed

You also need a semicolon following a class declaration, so the } character that follows each class declaration needs to be };.

After making those changes (and forward-declaring MyType, which I assume already is declared in your code), the code compiles.

Upvotes: 0

Related Questions