I think the ergonomics of `std::byte` lie as well, but it would take a lot of work to fix it.

I have once tried to chip away at the problem in https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3087r1.html by making it so that you can initialize std::byte using parentheses (or rather, enums in general) instead of just with braces, and that failed.

We should make std::byte a fundamental type and just make the type traits lie so that they tell you its an enumeration, or maybe not even that, because who relies on it being an enum anyway?

Another less invasive thing would be to allow initializing std::byte using integer literals, despite it being an enumeration, which would greatly improve its ergonomics.

Making another std::byte2 is definitely the worst option and just compounds the issue.

My current advice is to not use std::byte. It's academically the best byte type and practically the second worst. Just use unsigned char and you will have more joy.

On Thu, 25 Jun 2026 at 15:34, Rune Lund Olesen via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hello All,

The current std::byte has some deep issues in that it is too opaque to the point it is flawed by design.
(we know it is in reality a scoped enum).
Especially this comes up in generic code where it is cumbersome to add specializations because it is not a fundamental type.

A "better" way would be a real fundamental type or struct that mimicks it...

Overall it should at least behave like a fundamental uint8_t/unsigned char in most respects
and be easy to convert to/from...
except ofc. it shouldn't be an arithmetic type and it shouldn't be treated like a textual "char" as we know.

See below for a quick draft up...

Kind regards

Rune Lund Olesen
(writing c++ for ~20 years)
Senior Engineer
Gatehouse SatCom
Denmark (sorry for possible quickly written english)

namespace std
{
    struct byte2 {
        byte2(){};
        byte2(uint8_t value) : value{value} {
        }

        explicit operator uint8_t() const {
            return value;
        }

        // more usefull functions, overloads, whatever

        uint8_t value{};
    };

    template<>
    struct is_fundamental<std::byte2> : true_type {
    };

    template<>
    struct is_unsigned<std::byte2> : true_type {
    };

    //more type traits
}
static_assert(std::is_fundamental_v<std::byte2>);
static_assert(std::is_unsigned_v<std::byte2>);

void f() {
    std::vector<std::byte2> mybytes{};
    std::vector<uint8_t> mybytes_uint {mybytes.begin(), mybytes.end()};

    std::byte2 b;
    uint8_t f;
    //f = f + b; //will give compiler error
}

--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals