Jump to content
  • Advertisement

Oberon_Command

Member
  • Content Count

    4322
  • Joined

  • Last visited

  • Days Won

    2

Oberon_Command last won the day on October 20 2018

Oberon_Command had the most liked content!

Community Reputation

6322 Excellent

1 Follower

About Oberon_Command

  • Rank
    Contributor

Personal Information

  • Role
    Programmer
  • Interests
    Design
    Programming

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. To be clear, what I'm actually looking for is to be able to do this: struct Point { int x; int y; }; Point a = get_point_a(); Point b = get_point_b(); if (a == b) { // ... } Which currently I cannot, because operator== is not defined automatically. I want the compiler, for simple types, generate an implicit operator== just as it does an implicit copy constructor, without my having to overload anything. Furthermore, my argument is that the reasonable default is member-by-member comparisons. A strong typedef doesn't actually change the type, though. It would just disallow implicit conversions with the type it aliases. So no, I wouldn't want a deep compare operator== in that case, because the actual type of cstring is still a pointer type and it still behaves like one in all other respects. "C-string" means "pointer to string." If you wanted to write a wrapper type that did deep equality, that would be fine with me, but then I'd say it should be called something else, like "weak_string" or "string_view" (which we have in the standard!). I doubt that's really going away any time soon. Booleans being implicitly castable to integers is probably necessary for C compatibility. I suspect there exists at least one "load-bearing bug" that depends on this behavior and changing it would break somebody's code.
  2. I'd be fine with just automatically calling operator== on each member as the default. We already get that with the implicit copy constructor/assignment operators. If the default doesn't do what I want, I'll override it, but most classes I work with are just doing that, anyway. It's the most usual case and therefore should be the default and automatic one. My assumption is that the standards committee, being highly concerned with the implementation of the standard libraries, often encounters cases where this is not the default situation. It seems to me that, in general, there is a distinct trend of the standards committee prioritizing library authors when adding new features and rules. Or perhaps this is an aspect of the "zero cost abstractions" philosophy and the committee doesn't want to force (what I consider) the reasonable default on everyone on the grounds that it would be a default with potential runtime costs. But... we already have that, with copy constructors... And now I'm just speculating. My expectation here as a C++ programmer would be deep equality, because that's how the standard library types generally behave and how the vast majority of user types I have encountered in production code behave. If I wanted identity rather than equality, I would compare the pointers or similar - eg. handles, in cases where my data is double-buffered or relocatable. If you want to do something else in your own idiom, that's fine, that's why we have operator overloading, but in C++ I'm always going to expect a deep comparison and you should specifically tell me when the type is doing something different. IMO operator overloading should be reserved for non-default cases and should not be required for holding the compiler's hand through the default ones. It seems intuitive enough if you keep in mind that char* as "pointer to string" rather than "string value." I would further argue that this is the correct way to think of a char* and "a == b" in your example is the behavior that I would expect. What's unintuitive or odd about this? It's certainly not always convenient, but the idea that comparison operators are binary (and more complex conditions are created by composing them) is a simple and clear one.
  3. My experience is otherwise. Once the basic formatting rules are set, programmers will then proceed to argue over naming conventions, whether to use struct or class, whether to use type aliases, how deeply to nest namespaces, how to split related code into multiple files (and whether to do that in the first place)... I could go on at some length with more examples. My point is that "style" is a lot more than just formatting.
  4. It is unclear to me what would justify that feeling. The purpose of a style guide is to provide canonical answers to common questions regarding how to write the code to keep the programmers from arguing with each other and cut down on the cognitive burden incurred by interacting with the code via well-known conventions for common situations. If management (rather than tech leadership) is imposing the style guidelines, then they're doing style guides wrong, because the style guide should be driven by the developers, for the developers.
  5. Since you mentioned copy/move constructors I'm assuming this is specifically in C++. IMO a lot of your wants can be addressed by changing your idiom a little. On most classes in a modern idiom you don't need all of those things unless you're specifically writing your own containers. Furthermore I'd argue that some of your complaints aren't actually all that bad. Some points: the standard seems like it adds more and more cases where inline initializers are supported every iteration; we can now assign defaults to fields for a lot (but not all) types separating the default constructor from the class definition is actually a good thing in C++ due to the silliness that is #includes. The separation lets you change the defaults without having to recompile the rest of the codebase you don't strictly need a constructor that just takes the 3 fields if you can use aggregate initialization you only need an explicit copy/move constructor if you're doing something different from what the default behavior is (ie. the class is an "owning" type and the ownership isn't handled by one of the fields); see the "rule of zero" same goes for destructors, the base class scenario aside (but you should be using inheritance sparingly) I agree on equality, that should be automatically generated and I've never been clear on why it isn't I'm not clear on what you propose to do differently for the ordering case, but you also don't need to have that be a feature of the class itself if you're using sorting algorithms that take sorting predicates (because then you can specify the ordering in those). Personally, my biggest gripe with C++ is everything to do with #includes (which leads to people working around the problem in mutually incompatible ways; it's no wonder single-file and header-only libraries have taken off!) and especially the fact that the standard headers don't follow an "include what you use" philosophy, but C++'20 is theoretically fixing that with modules. Second biggest is probably how the standard doesn't really have a good hash table (unordered_map has some issues that affect perf). Biggest gripe with C# and Java is that they don't seem to understand that free functions can actually *promote* encapsulation in a real-world codebase and therefore disallow them. Java's generics erasing the type of the thing stored in them and requirement that primitive types be boxed (though at least the language does this automatically) to be stored in generic containers or passed to generic methods is a bit irritating. Java's lack of reference arguments (which makes writing a sort method that works on stack types impossible). Java's lack of stack types (and C#'s distinction at the type level between stack and reference types). Any expression of the form "Type x = new Type()." I shouldn't have to specify the type more than once in the statement. This is one reason I'm grateful the auto keyword exists and remedying this is the most common use of auto I see in C++.
  6. Unreal's Blueprint visual scripting system sounds close to what you're looking for, but programming that isn't text-based is still programming. If that's too much programming for you, then all I can really suggest is that you get into modding. A "total conversion mod" for an existing game - where you replace all the assets with new ones to get a new game that has the same or very similar gameplay as the old one - might be what you're looking for here. Without knowing anything about your target experience it's a bit difficult to suggest which game to use as a base, however, and most games are not built to support modding in any meaningful sense. And then on top of that there's the potential copyright issues. But if you want to build something truly novel, I don't see any alternative to either programming or collaborating with someone who does. You say you were a C programmer, so you're clearly capable of programming, so what's the issue with picking up a different language? Unity uses C# as a scripting language, for instance. Development in C#, being a garbage-collected multiparadigm language with a rich standard library and lot less to think about than C, is typically quite fast and the code footprint can be substantially smaller than the C equivalent. There are frameworks for Python and JavaScript, as well, which are a lot less low-level than C. Have you ruled out these languages and frameworks?
  7. What if you actually want two groups of listeners that get called in different contexts? How are you going to handle the case where you're constructing and calling listeners on multiple threads (eg. we enter vector's push_back on both threads at the same time)? What happens if a listener is in the middle of doing something unrelated on another thread when _Listener_UpdateAll is called? Is Listener responsible for unregistering itself, and if so, how are you going to ensure that classes implementing its interface actually do that? This isn't the worst possible use of global state, but I'm with All8Up in that we should generally be skeptical of global state. I would also say that having to call Update manually is a feature not a bug. In general you will find it easier to read, understand, and debug code where the control flow and data dependencies are explicit.
  8. Oberon_Command

    Game Engine or custom game engine?

    Well, in those cases, if the tech is known and the game needs it, then presumably that game will implement it. But heavily physics-based games are uncommon for a variety of reasons that don't involve the tech side. Game engines need to provide a common set of tools that all their users want; they try to serve the common case, not the exceptional case. And yes, for many users of the major engines, the status quo is "good enough." Apart from the AAA space, most games don't push the limitations of their engine in any particular way. And when they do, the pushing is in the form of "how many things can I have on screen at once" and "how much art content can I stuff into this game."
  9. Oberon_Command

    Game Engine or custom game engine?

    In my experience, animators usually want a lot of control over the animations of living bodies and are not typically happy about yielding control to the physics engine. When they use mo-cap, they want the animations to look like the mo-cap. You can extend this somewhat to rendering, too. If the engine produces results that are physically accurate in terms of lighting, but not what the art director wants, then it's the engine that's going to change. Artist/designer/animator vision takes priority. "But this is what it really looks like" is not an argument that usually holds a lot of water. Sounds great for indie devs without the budget for motion capture or lots of animators. Reminds me of this talk:
  10. Oberon_Command

    Game Engine or custom game engine?

    I would also add to what Promit said that the disinterest in exact analytical solutions to graphics also extends to gameplay/physics code. Networked games in particular often have lots of "tricks" to make physics with 100+ms of latency believable. Yes, it's bad if your ragdolls vibrate when they're at rest, but nothing needs to be exactly accurate. It just needs to be believable in the context of the game. As I've said in the past, the vast majority of video games are not simulations. They are magic shows. We only need to trick the player into thinking that they are playing a simulation of an alternate reality. Players do not generally care if our simulation is accurate. They do not care whether we use splines or polygons or deferred rendering or forward rendering or PhysX or Havok or Bullet. Players care if our game is fun, if the controls are responsive, and if the graphics are beautiful. Furthermore, most games are not solely concerned with rendering inanimate objects like tanks that an engineer can model with a bit of time. How well do splines and patches play with skeletal animation? Facial animation? And can they do that with an acceptable loss of performance on current (or last) generation GPUs? I don't see anyone using engineering CAD tools to model faces, either.
  11. Oberon_Command

    Propagating const in PIMPL

    No, you can't, and disallowing member functions will not solve that problem. It's perfectly possible to pass a nullptr to a free function that expects a reference, too! void DoThing(int& x) { // passed in a reference, we expect this to be okay x += 5; } void SomethingCompletelyDifferent() { int x = 0; int y = 0; int* ptr = nullptr; if (GetSomething() == 3) { ptr = &x; } // 500 lines later DoThing(*ptr); // oops, I forgot my null check }
  12. Oberon_Command

    Propagating const in PIMPL

    I'm still not following you. The usual way to handle optional arguments is to check for nullptr in the parts of the function that use the pointer. void Function(int x, int y, Foo* optFoo) { int result = Frobnicate(x, y); if (optFoo) { int fooResult = optFoo->Frobnicate(x, y); optFoo->Blarggag(x, y, result + fooResult); } } Is there some reason you can't do that? What alternative are you trying to do?
  13. Oberon_Command

    Game Engine or custom game engine?

    I suggest that they probably weren't expecting you to have *written* a million lines of code. I don't think anyone expects that of junior developers. The phrasing you used here is "how many lines experienced." I would assume that they were asking about whether you had worked in a codebase that large before. I suspect based on this that they already have a codebase that large and are looking for people who are comfortable working in those sorts of circumstances. I suggest that if game artists wanted to deal with building, rigging, and animating spline-based models, and programmers wanted to deal with optimizing their rendering, then game engines would support them. Currently I don't believe that is the case. Quality generally takes a back seat to performance and tools support in the video game industry. Remember, video games are magic shows. They don't have to look exactly accurate, they just have to look "not wrong." Many corners are cut in the name of performance. Also, source on DX11 supporting splines-based rendering? I googled, but I can't find anything on this. DX11 does support tesselation, but that's not the same thing.
  14. Oberon_Command

    Propagating const in PIMPL

    So, if I understand this correctly, you're avoiding having member functions because they might get called on a null object pointer? At the risk of sounding flippant why not just write your code so that doesn't happen? I feel like there's some context that we're missing here that you aren't telling us that would make the post I quoted justify not using member functions, because I don't feel currently that it does and I want to understand why you think it does, because that will help us understand your actual problems better. Bregma's solution is more or less what I would normally suggest. The "view" thing was just a way to get around the fact that it would require not having member functions (due to the lack of a visible class definition). If you don't need that, awesome, don't bother with it.
  15. Oberon_Command

    Propagating const in PIMPL

    Could you clarify what you mean by the bolded text?
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!