Closed KrisTC closed 8 years ago
You can define a UDL
for your codebase
gsl::byte operator""_gslb(unsigned long long value)
{
return static_cast<gsl::byte>(value);
}
Now you can gsl::byte bitmap = 0xFD_gslb;
(Assuming that your compiler has support for this)
Thanks @RicoAntonioFelix
That is a nice idea, unfortunately in my specific case I am stuck with VS2013.
UDL
is not supported until VS2015
The example in that paper uses the new rules for constructing values of enumeration types: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0138r2.pdf which were adopted into C++17 draft at the Spring 2016 meeting in Jacksonville, Florida.
Until you can use a compiler that implements those new rules, I suspect you're stuck with static casts or narrow casts that you can hide behind a nice constexpr function to_byte()
, which could arguably be provided by the GSL -- but I am not sure. That would be Neil's call.
@neilmacintosh, what do you think? Should there be a to_byte()
for older compiler support?
If not I am happy for this to be closed I can always write my own in my own library.
@neilmacintosh I have been playing around a bit more and I was wondering if you considered using a union for byte?
union byte {
unsigned char b;
};
This allows the desired initialization syntax even in older compilers:
byte x = {0x01};
The operators can all be updated to work fluidly too:
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator >> (byte b, IntegerType shift) noexcept {
return {b.b >> shift};
}
Allowing cleanly;
byte x2 = x >> 1;
@KrisTC I like the to_byte
idea. I think it's a reasonable thing to add the GSL while we wait for the initialization support to arrive in the standard (and compilers). Plus, it does aid readability of code. Would you like to offer a PR that adds this functionality?
I would prefer not to use a union
. With the addition of to_byte
it seems unnecessary and is too far from the proposed standard type definition.
@KrisTC A nice but critical property of the enumeration-based definition of byte
is that it retains all the efficient ABI property of the underlying integer type. For example, if you have a function passing a byte by value or returning a byte value, the compiler will try hard to use registers wherever possible and permitted by the target ABI. On the other hand, we do know that returning a union-type by value will actually be turned into "invisible" reference on popular architectures, so you take an abstraction penalty hit. It isn't ABI-transparent.
By the way, why would you prefer the union
-definition over a struct
or class
definition?
@neilmacintosh Thank you for the feedback, I am happy to do a PR for the to_byte method. I will do this as soon as I get a chance.
@gdr-at-ms Thank you for the explanation of the benefits of the enumeration-based definition. I am afraid to say I didn't put a huge amount of thought into it. I felt it made the size and alignment explicit and also to match "unsigned char", which I guess is odd with only a single member.
@KrisTC : Are you aware, that usage of gsl::byte currently leads to undefined behavior? E.g. see this issue: https://github.com/Microsoft/GSL/issues/313
@MikeGitb, thanks for that. I will test in VS2013, but from the comments it looks like I will be ok because MSVC works, I only work with MSVC.
@neilmacintosh I have completed my first ever PR. Sorry it took so long, I need to get permission from my employer.
It looks like all the checks have passed: https://github.com/Microsoft/GSL/pull/352
Thanks for identifying and fixing this issue @KrisTC!
At my company we recently ran into a severe defect in the field that is caused by use of a char* as a byte. We have fixed the issue, but I would rather switch our definition of byte to use the GSL one. However I it doesn't define any operator or method to initialize from an integer.
I saw the submition for the standard type: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0298r0.pdf and followed it's initalization example but unserprisingly it doesn't work. I am using Visual Studio 2013 compiler with warning level 4.
Gives the following error:
Using a static cast works, but is ugly I was wondering if a to_byte method to match the to_intetger method would make the usage a bit nicer:
Or can people think of something nicer?