Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sending enumerations in sf::Packet with C++11  (Read 4318 times)

0 Members and 1 Guest are viewing this topic.

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Sending enumerations in sf::Packet with C++11
« on: December 23, 2014, 12:18:05 am »
A while back I was having some issues regarding sending enums through sf::Packet. The primary solution was to cast the enum to an int, send it, then do more casting on the receiving end. The resulting code looked something like this:

enum class MyEnum
{
   VALUE1,
   VALUE2
}

...

// Sending
sf::Packet oPacket;
oPacket << static_cast<std::uint8_t>(MyEnum::VALUE1);

...

// Receiving
std::uint8 ui8Value;

sf::Packet oReceived;
// receive the packet
oReceived >> ui8Value;
MyEnum eMyEnume = static_cast<MyEnum>(ui8Value);
 

This is quite messy and verbose and its horrible to maintain, especially if MyEnum grew to include values which exceeded values of 255.

The simple option would be to cast everything to either int32 or in64 (And their unsigned counter-parts), but thats boring (And casting is ugly).

So I wrote some sf::Packet<</>> overloads to allow sending enums through sf::Packet with the help of templates and C++11 underlying types for enumerations and type traits:

template<typename T>
inline typename std::enable_if<std::is_enum<T>::value, sf::Packet&>::type
operator<<(sf::Packet& roPacket, const T& rkeMsgType)
{
   return roPacket << static_cast<std::underlying_type<T>::type>(rkeMsgType);
}

template<typename T>
inline typename std::enable_if<std::is_enum<T>::value, sf::Packet&>::type
operator>>(sf::Packet& roPacket, T& reMsgType)
{
   std::underlying_type<T>::type xMsgType;
   roPacket >> xMsgType;
   reMsgType = static_cast<T>(xMsgType);

   return roPacket;
}
 

The code is probably a bit overkill, but it handles the correct casting for implicit enum types (signed int) explicit types.

The resulting send/receive code would look like this:
// Sending
sf::Packet oPacket;
oPacket << MyEnum::VALUE1;

...

// Receiving
MyEnum eMyEnume;

sf::Packet oReceived;
// receive the packet
oReceived >> eMyEnume;
 

The code has been tested and works as far as I have tested it.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sending enumerations in sf::Packet with C++11
« Reply #1 on: December 23, 2014, 09:40:09 am »
Indeed, after SFML switches to C++11 we can probably add this kind of stuff.

Tiny improvement: move the enable_if test to the template parameters, to avoid this big mess in the function signature.

template<typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
sf::Packet& operator>>(sf::Packet& roPacket, T& reMsgType)
Laurent Gomila - SFML developer

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: Sending enumerations in sf::Packet with C++11
« Reply #2 on: December 23, 2014, 12:40:13 pm »
Thanks for the tip. I cant inline the  function if I do it that way (As far as I know) and I'm too lazy to make a .cpp file for it.

As for the code itself, you (And the rest of the SFML team) are more than welcome to include it in the C++11 version of SFML if you think its good enough.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sending enumerations in sf::Packet with C++11
« Reply #3 on: December 23, 2014, 12:56:59 pm »
Quote
I cant inline the  function if I do it that way (As far as I know) and I'm too lazy to make a .cpp file for it.
It's a template function, it is inline by definition. If you try to put it in a .cpp file you'll get linker errors.

Quote
As for the code itself, you (And the rest of the SFML team) are more than welcome to include it in the C++11 version of SFML if you think its good enough.
We haven't started to work on the C++11 version of SFML yet, but we'll most likely include it, yes. Thanks.
Laurent Gomila - SFML developer

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: Sending enumerations in sf::Packet with C++11
« Reply #4 on: December 23, 2014, 01:09:25 pm »
Quote
I cant inline the  function if I do it that way (As far as I know) and I'm too lazy to make a .cpp file for it.
It's a template function, it is inline by definition. If you try to put it in a .cpp file you'll get linker errors.

I didnt know that one, oops. I thought template functions COULD be defined in source files. Anyway, no problem. If you need help moving to C++11 I'm more than happy to help out if you need.

Neil

  • Newbie
  • *
  • Posts: 27
    • View Profile
Re: Sending enumerations in sf::Packet with C++11
« Reply #5 on: December 28, 2014, 02:09:16 am »
You can put them in a source file but you have to explicitly instantiate it for every allowed parameter which is quite restrictive so usually avoided.