-1

So normally I wouldn't ask a question like this because it seems like it could be opinion based or start some sort of verbal war on coding practices, but I think there might be a technical reason here that I don't understand.

I was looking over the code in the header files for vcpkg (a library packing manager that Microsoft is creating and is "new" code) because reading code generally is a good way to learn things you didn't know.

The first thing I noticed was the use of using rather than typedef.

Snippet from 'https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/parse.h'

template<class P>
using ParseExpected = ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>;

I haven't personally used using this way before and an answer from: What is the difference between 'typedef' and 'using' in C++11?. Essentially, using is the new way to do it, and the benefit is that it can use templates. So Microsoft had a good reason to use using instead of typedef.

Looking at 'https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/commands.h' I noticed that they did not use any classes. Instead it was only namespaces with a function or so in them. ie:

namespace vcpkg::Commands
{
    namespace BuildExternal
    {
        void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet);
    }
}

I'm guessing that part of this is that the calling syntax looks essentially just like a static member function in a class, so the code performs the same but maybe saves some overhead by being a namespace instead of a class. (If anyone has any ideas on this too that would be great.)

Now the main point of all this. Why is Microsoft using structs instead of classes in their namespaces?

Snippet from 'https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/parse.h':

namespace vcpkg::Parse
{
    /* ... Code I'm excluding for brevity ... */

    struct ParagraphParser
    {
        ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {}

        void required_field(const std::string& fieldname, std::string& out);
        std::string optional_field(const std::string& fieldname) const;
        std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const;

    private:
        RawParagraph&& fields;
        std::vector<std::string> missing_fields;
    };
}

Searching stackoverflow, I found an old question: Why Microsoft uses a struct for directX library instead of a class? Which the answers were essentially, you don't have to declare things as public as default and a comment way at the bottom saying that it was old code.

If vcpkg was old code I would be completely satisfied, however, this is new code. Is it just some style they have that is a carry over (but using vs typedef isn't)? Or is it to save a line of code (public:)? Or is there some sort of overhead benefit? Or some other thing I haven't considered at all?

Questionable
  • 768
  • 5
  • 26
  • 5
    Why does it matter? a `struct` is a `class` and a `class` is a `struct`. – NathanOliver Jan 16 '20 at 17:37
  • 3
    If I had to guess, it saves lines by avoiding having to write `public` and then `private` later on in the class definition. Saving 1 line of code is the only measurable difference. – alteredinstance Jan 16 '20 at 17:37
  • 3
    The default behavior of `struct` is often what you want. This does not only include `public` vs `private` members but more importantly `public` (`struct` default) vs `private` (`class` default) inheritance. In my opinion, you will much more often need `public` inheritance and this is not as clear as with members, where one mostly has both types and can differentiate between them. So you have a small advantage through `struct` and none trough `class`. Why shouldn't they use `struct`? – n314159 Jan 16 '20 at 17:41
  • IMHO, you should focus on your coding guidelines and styles and only use other coding guidelines as recommendations or influences. So far, there is no one coding guideline that fits all. Here are few: MISRA, Microsoft, Google, and Amazon. There are static analysis tools that recognize a lot more. – Thomas Matthews Jan 16 '20 at 17:42
  • 1
    Speaking of `typedef` vs `using`; `using` does *everything* that `typedef` does/did + *more* and is a lot more readable in many situations, so avoiding `typedef` and using *only* `using` makes a lot of sense to me. – Jesper Juhl Jan 16 '20 at 17:53
  • @n314159 Well I have gone from thinking it was not a good idea to use `struct` for clarity reasons to thinking that `struct` is the way to go. – Questionable Jan 16 '20 at 18:46
  • Does this answer your question? [When should you use a class vs a struct in C++?](https://stackoverflow.com/questions/54585/when-should-you-use-a-class-vs-a-struct-in-c) – Questionable Jan 24 '20 at 19:48

3 Answers3

5

The only differences between struct and class are:

  1. the default member access (public vs private) and

  2. the default inheritance if you inherit from the type (public inheritance vs private inheritance).

The end result of 1 will be the same once the author has finished adding public:/private: to the type. 2 you can easily control yourself by being explicit when you inherit, rather than rely on the default. It's hardly a big deal and doesn't really matter.

As to why Microsoft uses struct rather than class in their code, you will have to ask some Microsoft people.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
1
  1. To be (more) compatible with C
  2. To avoid making everything public by using the public: keyword, since that all COM objects for example have only public member functions.
Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
1

Regarding the free functions vs static functions, I don't think there is any overhead in this with classes (I haven't measured this at all, I would just think that most compiler would recognize that the class is basically just a namespace for the function). The thing is just: You don't need a class.

Using a class with only static functions is basically abusing the class as a namespace. So if you are only doing that, then be explicit about it and just use a namespace. Having a class there would only be confusing since you would think that maybe there could be some state here and just see that there is non when you see that the function in the class is static.

This is especially relevant if this is used a bit wrongly. Imagine someone instantiates a class A a with static member function f to call a.f(). It is no problem regarding performance, since the construction is a no-op and it will pretty much be equivalent to A::f(). But for the reader it seems like there is some kind of state involved and that is just confusing.

Regarding the other two: using is just superior to typedef throught being able to use templates and is (IMO) better readable. The struct vs class issue is just something over what has the better defaults, its not a big difference, but most often, what you want is what a struct does, so there is no reason to use a class.

n314159
  • 4,990
  • 1
  • 5
  • 20
  • Ah this makes sense. Having worked in C (no namespaces) and C# (everything must be in a class). The idea of showing no state hadn't crossed my mind, but I like it. Also, default public inheritance is nice! I can see benefits to this struct usage. – Questionable Jan 16 '20 at 18:07
  • That everything has to be a class is something that I have come to hate in Java, I haven't really worked with C# sofar. – n314159 Jan 16 '20 at 18:11
  • C# bascially is just Microsoft's version of Java. I guess one benefit of things like this is they create a clear standard across the board for everyone to follow. – Questionable Jan 16 '20 at 18:43