1

In Ada I can define the following generic (Equivalent to a C++ template) :

Generic
With function Sum( .. ) return boolean
Package XXXX is ……
End package

And later the generic can be instantiated as follows

Package XXXX_1 is new XXXX( Sum => Sum_Int );

In other words I can create an Ada generic package which requires a function to instantiate it, now how do I do this in C++? ie

template < *function_declaration* >
    class Stack { 
    };
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 2
    See __Possible implementation__ and __Examples__: http://en.cppreference.com/w/cpp/algorithm/for_each Or if this is too much then I recommend the book list: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282 – Richard Critten Apr 13 '18 at 11:51
  • 1
    There are no such things as packages in c++, but you can have function templates(http://en.cppreference.com/w/cpp/language/function_template) and class templates (http://en.cppreference.com/w/cpp/language/class_template). What problem are you trying to solve? – Tobi Apr 13 '18 at 11:55
  • 7
    can you describe in non-ada-speech what you want to do? I dont know ada and because of this i have no idea what you want to do – 463035818_is_not_an_ai Apr 13 '18 at 11:59

2 Answers2

2

You can simply use a non-type template parameter:

template <bool (*)(int, int> class PriorityQueue { };

// Instantiate:
PriorityQueue<&std::less<int>::operator()> myStack;

Unfortunately, what you see here is that int<int isn't actually a function in C++, but a built-in. Therefore we need the std::less<int> wrapper. It's common to wrap functions in types, precisely because of this:

template <typename Order = std::less<int>> 
class PriorityQueue;

// Instantiate, override default
PriorityQueue<std::greater<int>> myStack;
MSalters
  • 173,980
  • 10
  • 155
  • 350
1

In c++ you can achieve this using run time polymorphism, i.e. defining an abstract base class and deriving concrete classes from it. For example, in a XXXX class, declare a Sum method as pure virtual, and every classes inheriting from it have to implement that method (otherwise they stay abstract as well):

The base class:

class XXXX
{
public:
    virtual ~XXXX() = default;
    virtual bool Sum() = 0; //this has to be overridden
};

A derived class:

class XXXX_1 : public XXXX
{
public:
    bool Sum() override
    {
        // Sum implementation here
    }
};

The Sum implementation is specific of the XXXX_1 class. You can have more implementations, but a different class (derived from XXXX) is needed for each of them.

A more sophisticated pattern, which doesn't involve polymorphism at all:

typedef bool (*_Sum)(); // _Sum is now a function type

class XXXX
{
    _Sum _sum;
public:
    XXXX(_Sum s) : _sum(s){}

    bool Sum()
    {
        if(_sum != nullptr)
        {
            return _sum();
        }
        return false; //just a default
    }
};

When instantiating the above class, a function pointer is passed in construction, the Sum method will execute the passed in function and return its return value:

bool f() //this function matches the _Sum type defined above
{
    return false;
}

int main(int argc, char *argv[])
{

    XXXX xxxx(f); //we're passing a pointer to f function, here
    xxxx.Sum(); //execute f

    return 0;
}

Using templates, things can get even more generic:

template <typename F>
class XXXX
{
    F _f;
public:
    XXXX(F f) : _f(f){}
    bool f()
    {
        return _f();
    }
};

In the above class, the template parameter is now a function type, and the member function f has its same return type.

We can pass the _Sum function type defined above as F, and (in construction) a pointer to the function f defined above:

int main(int argc, char *argv[])
{
    XXXX<_Sum> xxxx(f);
    xxxx.f(); //execute f again
    return 0;
}

or whatever function of whatever type:

#include <iostream>

typedef void (*_Void)(); //another function type

void v(){ std::cout << "Hello" << std::endl; }

int main(int argc, char *argv[])
{
    XXXX<_Void> xxxx(v);
    xxxx.f();
    return 0;
}
p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35