Announcement

Collapse
No announcement yet.

C++17 Is Now Official

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    • I believe C++ instills fear in programmers, fear that the interaction of some details causes unpredictable results. Its unmanageable complexity has spawned more fear-preventing tools than any other language, but the solution should have been to create and use a language that does not overload the whole goddamn human.Erik Naggum

    Comment


    • #22
      Originally posted by pal666 View Post
      in real world, outside of your inflamed brain, complex tasks require many people and many man-hours
      large number of committee participants in recent years is a good sign of healthy c++ state and rapid development
      Too many people think like you, this is why many up and coming software nowadays suck more. You are the problem in the Open Source community.

      Comment


      • #23
        Originally posted by kpedersen View Post
        When I look around for libraries, if I see one that says it uses, boost, asio or C++ >= 11, I simply discard it and continue my search.
        Basically "modern" C++ is too awkward to port to multiple platforms and it is too complex to rip out the stupid parts.
        It also loves to do terrible async related designs which are simply not valid when adding to existing architectures.

        It is a shame because I still see C++ as the only valid choice of language when starting a new project. I just wish the next standard would focus on safety rather than feature creep.
        For example, it is ridiculous that iterators are so unsafe compared to std::vector::at(size_t) and yet required for accessing much of the STL.
        Smart pointers are a good step but still not quite there, for example if code within a member function indirectly wipes the last reference count to "this", then everything you do is basically on a dangling pointer to this. The std::weak_ptr<T>::lock() is close, but not quite there yet.
        If something doesn't suit your usecase, nobody forces you to use it. E.g. if you're iterating over the vector and changing it at the same time — obviously "iterators are unsafe", but this is not because language is awkward, it's because you're trying to use the wrong tool. For example I don't like streams — why should I use two lines of `std::cout` for what I can do with a single one of `printf`? So I just don't use it.

        Now let me tell you — I was lucky (or maybe not, depends on how you look at it) to get into serious programming after C++11 got released, and pretty much all C++11'ish I was taking for granted. And looking at C++03 from my perspective, I see it was real clumsy. No lambdas, no unions with complex members, no initialization with initializer lists, no returning initializer lists from functions… Whereas in C++03 I had to do return MyJITThread(1, 2, "thread1");, in C++11 and later I can do return { pid: 1, fd: 2, p_name: "thread1"};, now guess which one is more readable??

        Comment


        • #24
          Originally posted by kpedersen View Post
          When I look around for libraries, if I see one that says it uses, boost, asio or C++ >= 11, I simply discard it and continue my search.
          Basically "modern" C++ is too awkward to port to multiple platforms and it is too complex to rip out the stupid parts.
          It also loves to do terrible async related designs which are simply not valid when adding to existing architectures.

          It is a shame because I still see C++ as the only valid choice of language when starting a new project. I just wish the next standard would focus on safety rather than feature creep.
          For example, it is ridiculous that iterators are so unsafe compared to std::vector::at(size_t) and yet required for accessing much of the STL.
          Smart pointers are a good step but still not quite there, for example if code within a member function indirectly wipes the last reference count to "this", then everything you do is basically on a dangling pointer to this. The std::weak_ptr<T>::lock() is close, but not quite there yet.
          Unapproved message for you ↑ (well, I hope it is actually unapproved and not just disappeared).

          Comment


          • #25
            Originally posted by kpedersen View Post
            When I look around for libraries, if I see one that says it uses, boost, asio or C++ >= 11, I simply discard it and continue my search.
            Heh. Whereas in my opinion Boost is the greatest thing ever. You know that a lot of it ends up in the standard library after each update?

            And as for iterators, they are very safe. If you respect the invalidation rules for each container. You know that the `at(index)` function is only useful for vectors, partly useful for deque and completely useless for sets, maps, lists, etc. But iterators work for most all of them.

            Comment


            • #26
              Originally posted by r08z View Post

              Too many people think like you, this is why many up and coming software nowadays suck more. You are the problem in the Open Source community.
              I can assure you that he's more the minority than the majority in the open source community. It's silly to think that committees are a sign of health though, as they are typically the sign of the opposite -- committees are where ideas go to die. Committees are, far more often than not, far removed from the problem space that they are trying to solve. The same is true of the C++ committee being far off from the needs of the C++ community (if there even is one!). They take ages to get around to becoming aware of and solving real problems in the language, and by the time they do get around to addressing the problem, the solution is inadequate, and you're better off continuing to use third party solutions anyway.

              From what I've seen of the C++ committee and their solutions, they seem to largely be just following what other programming languages are doing, but they often choose to implement these features in rather awkward ways, which leads me to wonder whether they truly understand what they're doing in the first place. Even within the new C++17 update, I see a number of critical issues in their spec, compared to what other modern open source languages are doing with their implementations of these features. Serious issues still remain unresolved with this update, so it's evident that C++ development is still moving at a snail's pace.

              Nowadays, open source programming languages are driven by community rather than committee. Problems are identified, the community publicly discusses these issues, possible solutions are proposed, pros and cons to those solutions are outlined and discussed, and the solutions are tested in practice within a fork of the reference cross-platform implementation of that language. That way, they can identify whether the idea works in practice, rather than releasing a spec and waiting for compiler developers to implement the spec, then getting feedback after the spec is finalized, which can probably never be addressed because it's now in the standard.

              Comment


              • #27
                Originally posted by Hi-Angel View Post
                If something doesn't suit your usecase, nobody forces you to use it. E.g. if you're iterating over the vector and changing it at the same time — obviously "iterators are unsafe", but this is not because language is awkward, it's because you're trying to use the wrong tool. For example I don't like streams — why should I use two lines of `std::cout` for what I can do with a single one of `printf`? So I just don't use it.
                Although in modern systems languages, it's perfectly safe to mutate values when iterating. An example from Rust for iterating across an iterable type with mutable borrows:

                Code:
                for value in &mut vector {
                    *value += 1;
                }
                
                // Can also be written as so:
                for value in vector.iter_mut() {
                    *value += 1;
                }
                
                // Or as so:
                vector.iter_mut().for_each(|value| *value += 1);
                Now let me tell you — I was lucky (or maybe not, depends on how you look at it) to get into serious programming after C++11 got released, and pretty much all C++11'ish I was taking for granted. And looking at C++03 from my perspective, I see it was real clumsy. No lambdas, no unions with complex members, no initialization with initializer lists, no returning initializer lists from functions… Whereas in C++03 I had to do return MyJITThread(1, 2, "thread1");, in C++11 and later I can do return { pid: 1, fd: 2, p_name: "thread1"};, now guess which one is more readable??
                The issue I have with the second is that it's not very explicit about what it's returning. Seems to be returning an anonymous structure. In addition, unless this is the function that's responsible for initializing values of that type, it may be better to use something like
                Code:
                MyJitThread::new(1, 2, "thread1")
                , so that if you need to make an API change to your structure later down the road, you won't have to rewrite your initializations. For example, you may want to add some private types that are generated from the given input, or you may want to write a builder pattern so that the user can choose which parameters to fill in for their use case (needs optional type support though).

                Comment


                • #28
                  Originally posted by mmstick View Post

                  Although in modern systems languages, it's perfectly safe to mutate values when iterating. An example from Rust for iterating across an iterable type with mutable borrows:

                  Code:
                  for value in &mut vector {
                  *value += 1;
                  }
                  
                  // Can also be written as so:
                  for value in vector.iter_mut() {
                  *value += 1;
                  }
                  
                  // Or as so:
                  vector.iter_mut().for_each(|value| *value += 1);
                  You're changing values inside the vector — I meant rather changing the vector itself, e.g. removing values basing on some condition (though list data structure would suit better for such a use-case, but that's not the point).


                  Originally posted by mmstick View Post
                  The issue I have with the second is that it's not very explicit about what it's returning. Seems to be returning an anonymous structure.
                  I could understand this as an argument against using `auto`, but here you can immediately peek what's the type it returns. Your argument in this case is analogous to old WinAPI-style convention, who tried to tamp type names into variable names, like `pSomething`, `hWND`, `ppStuff` — like, what's the point? The type is not somewhere far away in files, it's right there under the eyes.
                  Originally posted by mmstick View Post
                  n addition, unless this is the function that's responsible for initializing values of that type, it may be better to use something like
                  Code:
                  MyJitThread::new(1, 2, "thread1")
                  , so that if you need to make an API change to your structure later down the road, you won't have to rewrite your initializations. For example, you may want to add some private types that are generated from the given input, or you may want to write a builder pattern so that the user can choose which parameters to fill in for their use case (needs optional type support though).
                  But I still have to change MyJitThread::new, don't I ? What's the difference?

                  Comment


                  • #29
                    I shall say there is still one thing I really miss — iterating over the macros arguments. E.g. as opposed to __VA_ARGS__ which inserts them all at once.

                    But I doubt though it's worth the effort of writing a proposal, because with time I think C++ would be phased out in favor of Rust.

                    Comment


                    • #30
                      Originally posted by Hi-Angel View Post
                      You're changing values inside the vector — I meant rather changing the vector itself, e.g. removing values basing on some condition (though list data structure would suit better for such a use-case, but that's not the point).
                      That's what the filter method is for:

                      Code:
                      for value in vector.iter().filter(|x| x == this) { }
                      vector = vector.into_iter().filter(|x| x == this).collect::<Vec<_>>();
                      I could understand this as an argument against using `auto`, but here you can immediately peek what's the type it returns. Your argument in this case is analogous to old WinAPI-style convention, who tried to tamp type names into variable names, like `pSomething`, `hWND`, `ppStuff` — like, what's the point? The type is not somewhere far away in files, it's right there under the eyes.
                      Not sure what you're talking about here.

                      But I still have to change MyJitThread::new, don't I ? What's the difference?
                      Not necessarily. Say you had a private field that stored the ID of the thread, and this ID was taken from a global atomic integer, so that the user doesn't have to specify the thread ID manually when initializing every thread. The point of using a constructor method is so that you can have private fields that are automatically initialized behind the scenes without the user having to manually specify every field by hand.
                      Last edited by mmstick; 05 December 2017, 09:06 PM.

                      Comment

                      Working...
                      X