OleksandrKvl / sbepp

C++ implementation of the FIX Simple Binary Encoding
https://oleksandrkvl.github.io/sbepp/
MIT License
39 stars 4 forks source link

Make TemplateId and BlockLength data members a part of the Message class #39

Closed ujos closed 4 months ago

ujos commented 4 months ago

Could you make the TemplateId and BlockLength a part of the Message class, so instead of

case sbepp::message_traits<schema::messages::MyMessage>::id():
  auto msg = sbepp::make_view<MyMessage>();

... I can do following:

case MyMessage::TemplateId:
  auto msg = sbepp::make_view<MyMessage>();

It is just too much of meta-programming. Meta-programming is nice. It just does not let the InteliSense do its job. I'd prefer write MyMessage:: and press Ctrl+Space. Instead I have to remember how to retrieve the TemplateId.

The same applies to composite size_bytes. Would be great to have MyComposite::Size static data member too.

ujos commented 4 months ago

I'm not sure though how can it be implemented, as MessageX class is a template based on the Byte...

OleksandrKvl commented 4 months ago

No, nothing can be added inside classes that have accessors. The reason is very simple: it's possible to have a field with name TemplateId or Size. Generally, there are 2 basic subsystems: the one that works with raw data and the one that provides static/meta information from schema XML via traits(I've created #40 to explain this better in docs). And they will not be mixed. However, I'll think about providing type->tag mapping(#41). I'm not sure that having 2 types instead of a single one is very problematic, considering that this happens in a single place when you dispatch incoming messages by types. For now, if you want to avoid it, there's a way:

case sbepp::message_traits<schema::messages::MyMessage>::id():
  auto msg = sbepp::make_view<sbepp::message_traits<
    schema::messages::MyMessage>::value_type>();
ujos commented 4 months ago

For now, if you want to avoid it, there's a way:

I know. it is just too much of glue. When I read this code, I do not see what is going on here. sbepp here, sbepp there. I'm loosing the business logic and an idea behind the traits and helpers. There is more of sbepp than my code :)

it's possible to have a field with name TemplateId or Size

Yes, it is possible but I haven't seen that in real life.

OleksandrKvl commented 4 months ago

As I said before in another thread, having "smooth experience", as you call it, is not the main goal. The goal is to provide basic generic building blocks from which users can create ad-hoc utilities for their specific needs. It's trivial to transform the above code to something like:

using messages = schema::messages;

case get_message_id<messages::MyMessage>():
  auto msg = create_message<messages::MyMessage>(ptr, size);

Even more, with a bit of TMP, you can have:

void handle_message(sbepp::message_traits<messages::msg1>::value_type<char> msg);
void handle_message(sbepp::message_traits<messages::msg2>::value_type<char> msg);
void handle_message(sbepp::message_traits<messages::msg3>::value_type<char> msg);

visit_messages<messages::msg1, messages::msg2, messages::msg3>(ptr, size, [](auto msg){
    handle_message(msg);
});