user3516222
user3516222

Reputation: 11

How to force derived class to implement a static function which receive as parameter an object of the derived class

I defined a class A, which define a static function. Let's say

class A{

  // virtual functions

  // the function create the object and sets its fields according to inputs
  static bool create(vector<string> inputs, A* a);

}

Is it possible to force the derived classes to implement the compute function in the following way?

class B : public class A{

  // virtual functions

  static bool create(vector<string> inputs, B* b);
}

class C : public class A{

  // virtual functions

  static bool create(vector<string> inputs, C* c);
}

Upvotes: 1

Views: 3750

Answers (2)

Gombat
Gombat

Reputation: 2084

A solution would be to have a base class calling a function of the derived class while using the Curiously recurring template pattern

#include <iostream>
#include <string>

// Declare a base_traits traits class template:
template <typename derived_t>
struct base_traits;

// Base class enforcing derived classes to implement a static foo()
template<typename derived_t>
class Base
{
protected:
  Base() {}
  virtual ~Base() {}

public: 
  static void foo(typename base_traits<derived_t>::value_type* val)
  {
    derived_t::foo(base_traits<derived_t>::value_type* val);
  }
};

// *** Derived A ***

// value type of A
struct A_result { int a; };

// derived A definition
template<typename T>
class A : public Base<A<T>>
{
public:
  A() {}
  virtual ~A() {}

  typedef typename base_traits<A>::value_type value_type;

  static void foo(value_type * val)
  {
    std::cout << "A::foo()" << std::endl;
  }
};

// specialization of base traits for A 
template <typename T>
struct base_traits<A<T>>
{
  typedef T value_type;
};

// *** Derived B ***

// value type of B
struct B_result { float b; };

// derived B definition
template<typename T>
class B : public Base<B<T>>
{
public:
  B() {}
  virtual ~B() {}

  typedef typename base_traits<B>::value_type value_type;

  static void foo(value_type * val)
  {
    std::cout << "B::foo()" << std::endl;
  }
};

// specialization of base traits for B
template <typename T>
struct base_traits<B<T>>
{
  typedef T value_type;
};


int main(int argc, char* argv[])
{
  A_result a_val;
  A<A_result>::foo(&a_val);

  B_result b_val;
  B<B_result>::foo(&b_val);

  return 0;
}

If the derived A or B are missing the foo() function, you will have a compile error.

Upvotes: 0

Christian Hackl
Christian Hackl

Reputation: 27528

No, there is no way. "Forcing" a class to implement a function can only be achieved with pure virtual functions (and even then you don't really force it, because the derived class may itself stay abstract).

Think about it. You are trying to combine two incompatible mechanisms of C++.

virtual always has something to do with objects. You have an object of some derived type and a pointer or reference to the base type. The whole idea of a virtual function only makes sense with objects.

static, on the contrary, does not require an object. The reason you use static in the first place is precisely that: you want to call something without having an object.

So it's just two different worlds, really. You are asking "How can I make the compiler choose a function at run-time depending on the derived type of an object without having an object?"

Perhaps what you are really looking for are templates. With a template, you can require that a type, when used in a certain context, has a certain function:

template <class T>
void f()
{
    T::compute(my_vector);
}

In any case, it seems that your actual goal is to solve a higher-level problem, but you are using the wrong tool for that.

Upvotes: 2

Related Questions