Live data from Hacker News

C++ Patterns: The Badge

awesomekling.github.io

51–60 of 160 posts

Re: C++ Patterns: The Badge

#51
post #45

This is a typical example of a solution to an artificial, self-imposed problem created by C++'s assumptions. As a programmer, I would feel frustrated to have to figure this out instead of spending time on something a user would actually care about.

Considering the whole problem could easily be solved with a comment: // should only be called by Device

Re: C++ Patterns: The Badge

#52

I like it! The self-documentation of where the call is coming-from is quite nice (though a more descriptive name like CallFrom would make that even clearer, were it the principle intent). I can't help myself, though: template Badge FakeBadge() { struct Stub {} return reinterpret_cast >(Stub()); }

You actually need:

  template
  Badge FakeBadge() {
    static struct Stub {} stub;
    return *(Badge*)&stub;
    };

Re: C++ Patterns: The Badge

#53

I like it! The self-documentation of where the call is coming-from is quite nice (though a more descriptive name like CallFrom would make that even clearer, were it the principle intent). I can't help myself, though: template Badge FakeBadge() { struct Stub {} return reinterpret_cast >(Stub()); }

Doesn't subvert Device badges for me. Complete sample: template class Badge { friend T; Badge() {} }; template Badge FakeBadge() { struct Stub {}; return reinterpret_cast >(Stub()); }; class Device { public: static Badge getBadge() { return Badge (); } }; void needDeviceBadge(Badge badge) { } int main() { needDeviceBadge(Device::getBadge()); // no error needDeviceBadge(FakeBadge ()); // error! return 0; } g++ errors:…

It does, however, work fine if you use a proper "* (Badge* )&stub" cast.

Re: C++ Patterns: The Badge

#54

Wouldn't -Wextra yell about the Badge being an unused parameter in the register devices? You would have to do some kind of dummy call that the compiler would have to optimize away.

There are attributes for that, standardized as of C++17 and available in most compilers much earlier. -Wextra won't yell about anything.

Re: C++ Patterns: The Badge

#56

I like it! The self-documentation of where the call is coming-from is quite nice (though a more descriptive name like CallFrom would make that even clearer, were it the principle intent). I can't help myself, though: template Badge FakeBadge() { struct Stub {} return reinterpret_cast >(Stub()); }

Doesn't subvert Device badges for me. Complete sample: template class Badge { friend T; Badge() {} }; template Badge FakeBadge() { struct Stub {}; return reinterpret_cast >(Stub()); }; class Device { public: static Badge getBadge() { return Badge (); } }; void needDeviceBadge(Badge badge) { } int main() { needDeviceBadge(Device::getBadge()); // no error needDeviceBadge(FakeBadge ()); // error! return 0; } g++ errors:…

Interesting, I'd always assumed reinterpret_cast was YOLO-anything-goes. You learn something every day ;)

Re: C++ Patterns: The Badge

#57

Could you make the badge the last argument and give it a default value, so you don't need the initialization at the function call? It looks a bit strange and would need an explanation for why the empty initialization list is there IMO. I'm not sure if it would work, cppreference has this to say about default arguments: > The names used in the default arguments are looked up, checked for accessibility, and bound at th…

Unfortunately, it doesn't work. The reason is that VFS cannot access private constructor of Badge.

Re: C++ Patterns: The Badge

#58

Could you make the badge the last argument and give it a default value, so you don't need the initialization at the function call? It looks a bit strange and would need an explanation for why the empty initialization list is there IMO. I'm not sure if it would work, cppreference has this to say about default arguments: > The names used in the default arguments are looked up, checked for accessibility, and bound at th…

Oh man, I got really excited when I saw this suggestion and got out of bed early to try it out.

Unfortunately it seems like default arguments can't use private constructors. Both GCC and Clang immediately fail at the declaration. Not fair, C++!

/home/andreas/src/serenity/Kernel/FileSystem/VirtualFileSystem.h:81:52: error: 'Badge::Badge() [with T = Device]' is private within this context

Re: C++ Patterns: The Badge

#59

Wouldn't -Wextra yell about the Badge being an unused parameter in the register devices? You would have to do some kind of dummy call that the compiler would have to optimize away.

If an argument is nameless, the compiler won't complain about it being unused.

No warning:

    void VFS::register_device(Badge, Device& device) { ... }
Warning:

    void VFS::register_device(Badge badge, Device& device) { ... }

Re: C++ Patterns: The Badge

#60

I used to carefully design my C++ code with public / private / protected / friend (and the pointer-to-impl pattern for "compile time private") but a few years ago I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. It's been great, made my programming life much easier. This badge thing is clever,…

yeah, python LOC > 5000 try to debugging it while some dude just modified your type instance's guts.
Post reply on HN