views:

210

answers:

2

Example first:

template <class HashingSolution> 
struct State : public HashingSolution {

  void Update(int idx, int val) {
    UpdateHash(idx, val);
  }

  int GetState(int idx) {
    return ...;
  }
};

struct DummyHashingSolution {
  void UpdateHash(int idx, int val) {}
  void RecalcHash() {}
};

struct MyHashingSolution {
  void UpdateHash(int idx, int val) {
    ...
  }

  void RecalcHash() {
    ...
    UpdateHash(idx, GetState(idx)); // Problem: no acces to GetState function, can't do recursive application of templates
    ...
  }
};

In this example I can pass MyHashingSolution to State class so State have access to HashingSolution's methods, but HashingSolution can't call GetState. Is it possible to work around this?

This is in the deepest loop. virtual function here drops the performance by more than 25%. Inlineing is crucial for me.

A: 

As a shot in the dark, considering the almost complete lack of information in the question (see comments): would templates be useful? They're often good for compile-time polymorphism.

To get any more potentially useful information, please explain the problem more. Look at the problem comments. Tell us why you know what micro-optimizations need to be made when you're still working on fundamental design. If there's anything non-mainstream about the compilation or execution environments, give us a few details.

David Thornley
+5  A: 

As jalf suggests in the comments, you probably want to use a variant of the Curiously Recurring Template Pattern (CRTP). That is, make MyHashingSolution a class template parametrised by the derived class:

template <typename D>
struct MyHashingSolution {
    typedef D Derived;

    void UpdateHash(int idx, int val) {
        ...
    }

    void RecalcHash() {
        ...
        UpdateHash(idx, derived().GetState(idx));
        ...
    }

private:
    // Just for convenience
    Derived& derived() { return *static_cast<Derived*>(this); }
};

In this case, because you want the derived State class to also be a template, you need to take the slightly unusual step of declaring State as a class template that takes a template template parameter:

template <template <class T> class HashingSolution>
struct State : public HashingSolution<State<HashingSolution> > {
typedef HashingSolution<State<HashingSolution> > Parent;

    void Update(int idx, int val) {
        Parent::UpdateHash(idx, val);   // g++ requires "Parent::"
    }

    int GetState(int idx) {
        return ...;
    }
};

The key point is that, provided State inherits from HashingSolution<State<HashingSolution> >, Derived is a derived class of HashingSolution<State<HashingSolution> > so the static_cast<Derived*>(this) downcast in HashingSolution<State>::derived() compiles and works correctly. (If you mess up and derive State from HashingSolution<SomeOtherType> instead and then try something that involves a call to derived(), the compiler will complain as the requirements for static_cast<> are not met.)

Then declare the concrete State class you want to use like so:

typedef State<MyHashingSolution> MyState;

Unfortunately this solution has the side effect that you will need to change DummyHashingSolution (and any other such types) to templates that ignore their one template argument, in order to make them usable as template template arguments.

j_random_hacker
The parent doesn't *have* to be parametrised. Although it's almost certainly better that way from a coupling standpoint.
Functastic
@Cache: Well, I assumed from the sample code that this was an important feature to the asker. (I myself would probably just make State a concrete class and use a typedef to control which HashingSolution was used, as it's unlikely you need >1 State types in a given program.)
j_random_hacker
Actually I need many States for simulation purposes. For different simulations I need differen but similar implementations.stati_cast was the key.
Łukasz Lew