how a container is searched should be abstracted away in the container's implementation
lol, no, god no. I think you got the STL completely wrong.
HN user
how a container is searched should be abstracted away in the container's implementation
lol, no, god no. I think you got the STL completely wrong.
Indeed. It should be:
TL;DR: concurrency is unspecified in _C99_.
Since it is specified in C11's memory model.
Anyone knows why anyone would impose these limits to crowdfunding?
In a non-deterministic garbage collector memory _might not_ be released when the last reference goes out of scope (and this is often the case).
forcing strict evaluation feels like a mess, template haskell feels like a mess, debugging space leaks feels like a mess, not to mention that the haskell learning curve is very high
Haskell is pretty good at a lot of things, so don't misunderstand me, Haskell it's really good! But, at the same time, it still has lots of room for improvement. I guess perfection doesn't exist.
Do that and tell us how many people use your language. We'll be waiting.
Why use new/delete when you have make_shared and make_unique?
Like 99.99999999% of the time you can use those. Like the only situation where I think they might be not enough is for some weird uses of placement new.
And reference counting also renders the point of determinism moot - now you never know if releasing a reference while trigger freeing a resource.
You know that releasing the last reference will. That is why the important concept is single ownership of resources and not reference counting by itself.
You asked for a situation where the lifetime of a resource can't be directly tied to the lifetime of a single storage location.
I don't think I asked for that but correct me if I did (maybe I'm just not understanding your point).
Anyways, could you elaborate why shared_ptr, unique_ptr, and weak_ptr don't work in that case?
The solution above works even if your graph has cycles. Of course if you know that it doesn't you can just build the graph with unique_ptrs.
It's simple. The key is that something has to have _ownership_ of the products. [1]
User decides to view a couple of orders. Orders reference products. Those products are managed by something (e.g. an unordered_map of shared_ptr). The order can check, is my product there? If so, i'll copy the shared_ptr to it. Otherwise, I create a shared_ptr for a product and store a copy in the manager. When the order's destructor is triggered, you check the count of the shared_ptr. If it is 2 (i.e. the order and the manager), the order removes the shared_ptr.
[1] Single ownership is the key concept, not reference counting which is just an implementation detail.
Could you elaborate?
I fail to see why you need cycles' support for that.
Have a vector of shared_ptr that own the objects in the graph and build a graph with weak_ptr ?
Removing an object is just as easy as removing an element from the vector. (If you test the weak_ptrs on use, that's actually the only thing you would need to do).
Then the lists should only have a weak_ptr to the object.
Something is handling both list [1], that something could own the object, or maybe something external to that. Giving ownership of the object to both list is a design error [2].
[1] e.g. if the two list are an implementation detail of a data structure, the data-structure itself could own the objects in the lists.
[2] Do non-deterministic garbage collectors that handle cycles allow you to have a resource with multiple owners? Yes. Should you do it? No, god, please don't.
Because it is deterministic? (i'm just guessing that what you call "proper" garbage collector is non-deterministic).
Furthermore, the only "advantage" I see in garbage collectors is that they can deal with cycles.
I say "advantage" because i'm of the strong opinion that having a cycle in your code is a software design error.
In Germany I get paid around 3.500 Euro brutto per Month for pursuing my PhD at my university. Same conditions as the parent post: expected duration 5 years, 20% work time dedicated to university,...
That's around ~44.000 Euros per year (including perks).
I interviewed in 4 companies before deciding to go for the PhD (all engineering jobs). The salaries varied from 45.000 to 55.000 Euros brutto per year, with one offer at 60.000 Euros.
Friends working in industry make around 50.000 Euros which matches with my experience. Making a bit less for working in _your_ PhD is a really good deal here. If you find the right PhD for you it can be very gratifying (plus you are working for yourself). OTOH my friends in industry work way less hours than I do, so if I had a family I would probably had never gone the PhD way.
well there is clang-format and clang-tidy and they are really easy to set up in CMake (I use "make format").
This is no gotcha; he deliberately shoots himself in the foot by using a "weird" integer type. The right solution is to use value_type from container/iterator_traits (that is what it is there for):
accumulate(begin(v), end(v), value_type{0});
Suggesting 0LL is just calling for trouble when someone realizes the vector didn't had to be long long and forgets to change the initialized value.IMO one of the huge screw ups of the design of the STL is making sizes unsigned. It means that you get a compiler error when writing:
for(auto i = 0; i < vec.size(); ...) {...}
since i and size() have different types. The worst part is that unsigned doesn't buy you that much (only twice as many elements).The lesson to be learned here is: don't use weird integer types unless you really need to, and then, you should know what you are doing. E.g. if I need a long index then I use
using Idx = long long;
accumulate(begin, end, Idx{0});
when I'm hacking, and struct unique_tag {};
using Idx = arithmetic_type<long long, unique_tag>;
when I'm serious to disable all implicit conversions and make these types of errors impossible.but I don't think "Run your code through a formatter when you're done hacking it together" is a viable, maintainable, or scalable policy.
Just hook clang-format or clang-tidy with your build system. A lot of projects do it.
You will be surprised how inconsistent people actually are, even in project where almost everyone is sticking to these practices at 100%. And the larger the project, the worse it gets (most people are inconsistent in different ways).
The only way to get this right is to either produce hard errors when they are violated (e.g. your code won't compile, or won't be committed) or do it automatically. clang-tidy is just the way to go.
Yes, it does. Drepper's two points on the mails are the same points I made above:
- your code is not valid C code, fix that.
- these changes are pointless, since _unused0 could create problems in another system using invalid C code.
So unless there is a very good reason why this cannot be fixed upstream (and it has too be much better than "sorry but we are used to write invalid C code"), then I sincerely don't see why this patch should be accepted.
The problem is where there are multiple contexts of what is "the" implementation.
The fact that the macro _unused doesn't conflict with NetBSD's implementation of libc doesn't mean that you should use it if you want portability. Sooner or later you are going to get this problem with a different libc implementation. You could submit a patch to that implementation to "fix" it, but you would be again avoiding the true problem, which is that the _unused macro is invalid C.
In ISO C (7.1.3): All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
In ISO C++ (17.4.3.2.1): Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
In both (7.1.3 / 17.4.3.2.1): Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
The rule of thumb is never give a name that start with an underscore (simple, right?).
That goes for C and C++. In C++ people think that they are a bit safer because of namespaces, but I've seen it create problems when someone writes an using directive in a header file (dont do this). It will work on their project but break yours. And finding which header is causing this is a nightmare in small-medium sized projects. In big projects it deserves to get someone fired.
Note: if you really want/need to break this rule, choose a name that will not conflict with anything! E.g. in Boost file guards have a randomly generated character sequence appended at their end. They are not doing anything "illegal", but is a policy they have just to be sure.
Well, I'm sorry to disagree with you but Drepper is right. In C and C++ identifiers starting with an underscore are reserved for the implementation. Standard library implementors deal with extremely ugly code full of underscores everywhere to avoid this sort of problems.
Accepting that patch is sending the wrong message. First, it would say that if your project is big/important enough, you can do whatever you want. Second, it would say that they are willing to fix these issues, which I think is even worse.
So IMO, he took the right decision for every project using libc, which is to reject your patch, and to tell you to fix your code.
If you decide to write non-standard conforming code, then you deserve what you get (probably ABI breakage).
Disclaimer: this is a rant, it is obvious that I don't like OpenCL and that I think that it was designed by monkeys so take it with a grain of salt.
In short: don't learn OpenCL. Both CUDA and C++AMP are good languages for programming heterogeneous machines and nVidia's Thrust and Microsoft's PPL are both excellent libraries to write efficient and reusable code. These language extensions are also strongly typed and come with really good tools. My advice is: learn any of them instead.
Why not OpenCL? AMD's Bolt library is the live proof that OpenCL is fxxxxx up beyond all repair. It is not meant for humans to write, nor for machines to understand.
Kernels are just character strings!!! This is just so wrong! Forget about using functors and lambdas as kernels, and forget about mixing kernels with templates. You will be better off using Python and PyOpenCL (which is great) that using C and C++. In C++ generating kernels is really hard, and generating kernels from expression templates is insanely hard.
Furthermore, this also means that the language is not typed at all!! Forgetting a semicolon in C results in a runtime error! Do you want syntax highlighting? Write your kernels in separate files! This is even worse than the way people used to write functors far away from the call site in C++03, at least they were in the same file!
As stated above my advice is don't learn it. Let it die. Your time is better spent learning CUDA/C++AMP and their libraries. The design rules for OpenCL have been "let's not learn anything from OpenGL" + "we need something, this is something, let's standarize this". This of course has resulted in an hilarious language that came after CUDA and was worse in every possible way.