2

There are two different algorithms being used throughout the code. Which one is chosen is determined at runtime by a parameter (e.g. true or false). I do not want to use if-statements each time the algorithm comes up.

So instead of writing the following every time

if (parameter==true)
    algorithmOne();
else
    algorithmTwo();

I want to set the algorithm at the beginning, like

if (parameter==true)
    algorithm()=algorithmOne();
else
    algorithm()=algorithmTwo();

and only use 'algorithm()' from this point forward.

How can I choose the algorithm at the beginning depending on a parameter after the code is already compiled?

Edit: How do you do that within the constructor of a class (since a pointer-to-member function is no regular pointer)? As both algorithms rely on member variables and functions of this class, it is inconvenient to derive a new class.

Solution: This could be solved with a virtual function and derived classes.

class Base
{
public:
    Base();
    virtual void algorithm() = 0;
    ~Base();
protected:
    double d;
    int i;
    ...
}

class DerivedOne : public Base
{
public:
    DerivedOne() : Noise() {};
    void algorithm() override;
    ~DerivedOne();
};

Base *b;

if (parameter==true)
    {
        b = new DerivedOne();
    }
    else
    {
        b = new DerivedTwo();
    }

Then the function can be called with:

b->algorithm();

And deleted with:

delete b;

This may not be the best way but it seems to work for me. See answers and comments.

Oliver
  • 53
  • 5
  • 4
    Sounds like a job for a function or a method pointer. – Refugnic Eternium Feb 04 '22 at 10:53
  • Check these two links 1) https://stackoverflow.com/questions/3053561/how-do-i-assign-an-alias-to-a-function-name-in-c and this one, 2) https://stackoverflow.com/questions/9864125/c11-how-to-alias-a-function – iwrestledthebeartwice Feb 04 '22 at 10:54
  • Many different ways, template your code, use pointer on function or `std::function`, use inheritance and strategy pattern, ... – Jarod42 Feb 04 '22 at 10:57
  • 1
    You can replace `new` / `delete` with `make_unique` and change the type of `b` to `unique_ptr`. `One` and `Two` are not needed as you can directly assign to `b`. – Sebastian Feb 08 '22 at 13:55

3 Answers3

4

You're almost there:

auto algorithm = parameter ? algorithmOne : algorithmTwo.

No (), you're not trying to call any function here.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    And both functions of course should have the same parameter types and return the same type. – Sebastian Feb 04 '22 at 11:21
  • @Sebastian: Indeed, else they wouldn't be interchangeable. – MSalters Feb 04 '22 at 11:24
  • Thanks! How do I write this inside a class constructor when algorithmOne and algorithmTwo are member functions of this class? (error: nonstandard form for taking the address of a member function) – Oliver Feb 04 '22 at 14:51
  • 1
    @Oliver: In that case, you could make `algorithm` a pure `virtual` function, and provide two different derived classes. Each derived class would implement one `override` of the algorithm. The parameter would then determine which of the derived classes to instantiate. – MSalters Feb 04 '22 at 15:44
  • I thought about that as well but in a derived class, algorithmOne cannot access the private variables and functions of the base class. It seems odd that there is no simple way (like your original proposal) within a single class. – Oliver Feb 04 '22 at 17:30
  • 2
    @Oliver: You're writing that base class yourself. `protected` is a trivial solution. – MSalters Feb 07 '22 at 07:52
2

The answer you are looking for is likely a function/method pointer.

The syntax for a function pointer is as follows:

typedef void (*MyFunctionPointer)();
MyFunctionPointer *algorithm;

void function(bool parameter)
{
    if (parameter)
        algorithm = &myFirstAlgo;
    else
        algorithm = &mySecondAlgo;
}

void anotherFunction()
{
    algorithm();
}

Please note that this approach works for C, C++03 and C++11. If you want to use auto on the global scope, you need to give it a default value.

Refugnic Eternium
  • 4,089
  • 1
  • 15
  • 24
2

The object-oriented way of doing this would be to define a base class with the algorithm interface:

class AlgorithmBase
{
public:
    virtual void algorithm() = 0;
    virtual ~AlgorithmBase() {}  // virtual destructor may be needed
};

Then implement classes for the different algorithm implementations:

class AlgorithmOne: public AlgorithmBase
{
public:
    virtual void algorithm();
};

void AlgorithmOne::algorithm()
{
   ...
}

and similarly for AlgorithmTwo and other implementations.

Now, you can define a pointer to an algorithm object containing the selected implementation and use that whenever the algorithm shall be executed:

   AlgorithmBase *algorithm = 0;
   if(parameter)
   {
      algorithm = new AlgorithmOne();
   }
   else
   {
      algorithm = new AlgorithmTwo();
   }

   ...
   algorithm->algorithm();  // Call the selected algorithm

   ...
   delete algorithm;  // Destroy algorithm instance before exiting
nielsen
  • 5,641
  • 10
  • 27
  • 1
    This is just not C++ style. For starters, the method you would implement is typically `operator()`, and you would use `std::function` to store these objects. That also sidesteps the need for `virtual` and a base class. – MSalters Feb 04 '22 at 13:15