0

I have a template class that needs a callable object to be passed to handle errors. The callable object must overload void operator()(const boost::system::error_code&), and its type is passed as a template parameter to make the class more generic (e.g. accept lambdas).

The class looks like this

template <typename AsyncStream,
          typename ErrorHandler,
          typename = std::enable_if_t<...>>
struct basic_api {
  ...
  private:
    AsyncStream sock_;
    ErrorHandler error_handler_;
};

Now, I want to create an instance of this class in another class that overloads void operator()(const boost::system::error_code&)

Test fixture example:

struct BasicApiTest : ::testing::Test {
    void operator()(const boost::system::error_code& err) {
        // handler errors
    }

    std::shared_ptr<basic_api<tikpp::tests::fakes::socket, ???>> api;
};

I tried to solve this by creating an additional class which has the error handling function overload, and then derive from it, like so:

struct error_handler {
    void operator()(const boost::system::error_code& err)
        // handle errors
    }
};

struct BasicApiTest : error_handler, ::testing::Test {
    using socket_type  = tikpp::tests::fakes::socket;
    using handler_type = error_handler;
    using api_type     = tikpp::basic_api<socket_type, handler_type>;

    BasicApiTest() : api{...} {}

    std::shared_ptr<api_type> api;
};

But this solution has a lot of limitations.

Is this doable in C++, or should I find another approach to pass error handlers?

  • What have you tried sofar ? I assume your question is about ,???>> which expects a type ? I'm not a C++ programmer, but in C# I have used delegate function types for error handlers. In C++ you may need to pack your error handler in a separate (abstract) ErrorHandler class and pass that. You could also consider to adapt a C# style and pass an error handling *delegate* in the constructor.. I can't go into details because I lack the skills in C++, but for using delegates in templates, you may take a look at https://stackoverflow.com/questions/23973914/c-like-delegates-in-c – Goodies Jun 11 '20 at 22:28
  • @Goodies Yes, my question is about those question marks. In C++ we have std::function that can be used as C# delegates, but they come with high performance and space costs, so I cannot use it. I was looking for a solution that uses template or anything with low overhead. – Ayman Al-Qadhi Jun 11 '20 at 22:39
  • 1
    Better not to derive from the helper class, but use composition instead. Also pls explain what doesn't work, exactly, and what limitations. – rustyx Jun 11 '20 at 22:46
  • In the other topic some 3rd party libraries are mensioned., you may consider using that ? success with your test unit ! – Goodies Jun 11 '20 at 22:47
  • @rustyx That's why I want a better solution, to eliminate the helper class. The biggest limitation is not being able to modify the class state in a clean way from the helper class. – Ayman Al-Qadhi Jun 11 '20 at 22:49
  • @Goodies The other topic answers use virtual functions (which have performance penalty). – Ayman Al-Qadhi Jun 11 '20 at 22:52

1 Answers1

0

First of all, your requirement is hard to understand. It sounds like a so called XY-Problem. Please see the description here.

The question is maybe not, how you can use templates or a special syntax. The real question is maybe different. I think, that you want to achieve something that can be easily down with a class hierachy. With a pure virtual function in the base class and overwritten functions in the derived classes.

But you mentioned somewhere that you think that the overhead is too big.

And therefore I assume that your question is about Static Polymorphism. And this is usally solved with the CRTP, "Curiously Recurring Template Pattern". In that you have a templated Base class and a derived Class, which derives from Base.

Please start by reading here.

I hope I understood you question. If not then please comment and I will delete the answer.

A M
  • 14,694
  • 5
  • 19
  • 44
  • Thanks for your answer. I want to avoid RTTI as much as possible because this code needs to run on an embedded platform, so maximum performance is a requirement. I cannot use CRTP either because basic_api class derives from std::enable_shared_from_this to manage its life time, and the class that uses it does not have to be stored in a shared pointer. – Ayman Al-Qadhi Jun 12 '20 at 22:09