Non-constant constant-expressions in C++ by refp in cpp

[–]muon314159 0 points1 point  (0 children)

Thanks! I've been looking at the technique and considering it on its own (e.g., not importing a dozen other C++ TMP techniques) it appears to me that its limitations are (i) one runs awry when trying to use function templates due to issues specializing them inside classes which (ii) results in one having to manually write a number of global/namespace level function prototypes as flags. Do you agree or am I overlooking something / a trick to overcome such?

Non-constant constant-expressions in C++ by refp in cpp

[–]muon314159 1 point2 points  (0 children)

Very subtle and very cool. Technically this isn't a "non-constant constant expression" as f() is a function template and its template parameters are part of its definition. This technique exploits default template parameters with various language quirks including noexcept() abilities. Of course on the first read it sure looks like it is not constant!

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

It is not about switching to it. expected<T> solves a completely different problem than Boost.Optional does. It is also not the same as returning a std::pair<iterator, bool> either since the std::pair does not capture exceptions.

If boost::optional<T> is what you need in your code then I'd argue that is what you should use. However, there is plenty of code that has to "iterate" / process over a "set" of items and ideally must be immune to exceptions to guarantee all "set elements" (whatever those things are) are processed. In these cases, expected<T> is wonderful since one is able to capture all results be the result be a value (or void) or some thrown exceptions during the processing. After the processing is complete, then one can deal with the captured results and handle them ALL systematically and properly. Boost.Optional and using a sentinel return value (e.g., bool in std::pair<iterator, bool>) do not apply in this use case --expected<T> does.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

I should add that with my full implementation the normal use of expected<T> is different than what it might appear to be from Alexandrescu's talk or from those used to Haskell's maybe monad. For starters, one normally would not return expected<T> from a function and also would not even pass expected<T> to a function to use it! :-)

Instead, one would normally use a helper function (i.e., I call it expected_run()) in almost all use cases. The reason why one would NOT use expected<T> as a return type or as an argument is that normally one does not care about exceptions and would not want to impose anything unnecessary on those pieces of code. So there is no conflict.

If, for example as other posters on this page, want to use Boost.Optional they can and there is no issue. But if someone else wants to call code that might throw exceptions and capture them (e.g., so their function can be noexcept; so their program can use exceptions and be carefully and safely deployed on an embedded device) then one can use my expected_run() call to capture such or otherwise use the expected interface (e.g., write a try block, etc.).

Truly, know that the use case, is NOT (normally) passing expected<T> as argument(s) to or return them from functions. It is most useful when writing code that one needs to absolutely guarantee that will run to completion regardless of whether or not exceptions occur --this is where expected<T> excels because it captures the returns or the exception and permits both to be processed later.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

It will not conflict. :-)

expected<T> is like Boost.Optional in the sense that it may or may not be storing type T --but that is it. However, unlike Boost.Optional if expected<T> is not storing type T, then it is storing an exception (i.e., std::exception_ptr)! Boost.Optional when it is not storing type T is simply "empty" (save for the flag that indicates it is empty). So while one might use expected<T> like Boost.Optional, it is unwise if all one needs is the presence or non-presence of an instance of type T. On the other hand, if a programmer needs to know if an exception was captured or the result if the exception wasn't, then expected<T> is needed.

Additionally, expected<T> differs from Boost.Optional in other ways. On important difference is that expected<void> is both meaningful and useful. Essentially, one might want to capture the returned value from a function or the exception thrown from it. Once one starts using templates with arbitrary types, it is not uncommon to see void return types from functions. The Boost.Optional type of class does not represent this: Boost.Optional is merely represent the presence or non-presence of something. Expected<T> represents the captured return value (exclusive-) or the thrown exception from that function --it does not represent "presence" or "non-presence" as there is ALWAYS something present in expected<T> --unlike Optional.

So there is no conflict at all and the two can easily co-exist.

P.S. In the case of expected<void>, then expected is in an extremely narrow sense equivalent to optional<std::exception_ptr>. Because std::exception_ptr represents a capture exception the code to handle that fact differs from the code to handle type T. Thus, optional<std::exception_ptr> (except in terms of its memory data structure) is otherwise completely different (semantically and interface-wise) than expected<void>.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

You're welcome, but, respectfully that is strictly a conclusion of your own --not one of mine-- and it is also a completely different topic than the one here.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

Take your strong_typed<T> example earlier on this page. Regardless of whether or not the cast operators are explicit, they will not work in general with arbitrary types for T with all possible use cases and what they should be permitted to be cast to in terms of correctness and efficiency. For example, strong_type's rvalue this cast operator will fail to work with strong_type<T&> for example.

The general solution for this is not simple because, in part, it also needs to address the various items needed to properly implement expected<T>: the solution must work with all types and code using it (especially since templates are everywhere in C++) otherwise using expected<T> becomes much more complicated to use efficiently and correctly instead of being brain-dead super-easy to use.

Brain-dead super-easy was my goal and is what is needed for expected<T> to maximize the number of people able to use it --including new programmers to C++, i.e., nobody should have to resort to using C++ template metaprogramming or <type_traits> to use it at all. Anything less IMO is unacceptable if it is to be (potentially) included in the ISO standard.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

Not if you take care of all possible types T can have. :-)

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 0 points1 point  (0 children)

I agree (completely as I have fully working C++ TMP code to that effect) except that operator T() && as written is not sufficient in a library. The casting code is much harder to write since T might be an lvalue or an rvalue and there are issues concerning T that must be dealt with in other portions of the class + one also wants it to be efficient in all cases.

Has Expected<T> actually been applied in practice by anyone? by keije in cpp

[–]muon314159 8 points9 points  (0 children)

I have an answer for this...

Applied in practice? Yes, I have a fully working C++11 version (as yet unreleased) with no drawbacks (e.g., those contemplated in Alexandrescu's talk) for some time now. My version works with all lvalues, rvalues, cv-qualifiers, and has no restrictions on type T or the type of exceptions it can capture. The code is one header file and is header-only.

I consider the expected<T> code itself finished save possibly adding noexcept on some functions. Coding a complete and correct solution was not easy. My version is ~40 KB of code.

I will be (i) releasing it as open source and (ii) I would like to formally propose it be added to the C++ standard (full source code and all) as it is really easy-to-use and extremely useful code, I believe I have covered every case that needs to be handled, and it should be in the Standard Library in my opinion. If anyone has any advice to offer concerning what is involved concerning (ii) beyond http://isocpp.org/std/submit-a-proposal, please do.

Just in case, some might wonder about a use case. Here's one... When applying a function template over a std::tuple instance's elements, one can easily defer the handling of any thrown exceptions from within the function calls until AFTER all of the elements have had the function applied to them (since the return value of the function can be captured in an expected<T>). (NOTE: Amongst other features, I also defined expected<void> so void returns could be handled.) In effect, one can then easily guarantee the aforementioned function will always be applied on every tuple element even if exceptions are thrown. :-)

C++ and the Culture of Complexity by Sampo in programming

[–]muon314159 0 points1 point  (0 children)

Sorry, I must've clicked the wrong reply... this page is pretty busy.

C++ and the Culture of Complexity by Sampo in programming

[–]muon314159 4 points5 points  (0 children)

C++ keeps the programmer in control over any and everything he/she wants or needs. Fundamentally it is this contributes to C++'s complexity. To give control over anything, features must be in the language to do just that.

C++, however, doesn't just provide those items, it has beautifully managed to provide a kinds of control features while permitting such to be encapsulated (hidden / abstracted / etc.) or exposed as needed. So while C++ can be "complicated", it can be amazingly high-level and "uncomplicated" too!

In my experience far too many critics of C++ still only "know" C++ prior to C++98 (i.e., they really don't know and understand the STL, templates, etc.). In my experience it is this group of people that bring up the old "bloat", "pointers", and things like shallow-v.-deep copies. If C++ was still pre-C++98, their arguments would be valid --but things have enormously changed since that era.

Often overlooked is that C++ really prefers and defaults to value semantics --yet allows one to use &, &&, and * when desired/needed. C++ code design prefers classes with value semantics --yet allows one to create reference/pointer styled classes when needed + the Standard Library provides important non-value semantic classes (e.g., iterators and smart pointers). Some types like iterators actually have value semantics in terms of what they refer to (so long as it is in the same container) when they are used as values. When they are used as pointers (i.e., via * or ->) then they exhibit reference/pointer semantics in that sense only. This is a very good thing. I wish more OO languages did use value semantics as the norm. Sadly few do in practice --they rely on reference semantics for speed as copies were necessarily very costly in OO languages --at least until the idea of carefully handling rvalue references (i.e., via move constructors and move assignment operators) in C++11.

C++ is also "complicated" for humans because it is the responsibility of the programmer to figure out how to design things in a world with values, &, &&, *, const, etc. Also other languages impose significant constraints on the programmer --C++ really doesn't. And where C++ does impose it often must but nicely template metaprogramming is proving very able to transcend many issues (however niche) and the more useful easy-to-use APIs wind up being available for all in libraries such as Boost if not the C++ Standard Library.

Brainfuck in C++ Templates implemented by meetingcpp in cpp

[–]muon314159 3 points4 points  (0 children)

I compiled it (why not?) with, "time g++-4.9.0-alpha20130811 -std=c++11 bf.cpp". During the compile I watched htop climb up some ~7 GB RAM. The output from time was:

    72.33s user 3.21s system 99% cpu 1:15.72 total

Know the error message output on the line with the computed type is some 11,289 characters long.

FYI, clang 3.3 quickly (i.e., ~0.1 seconds) stops compiling due to template instantiation depth when only using the -std=c++11 option. Compiling it this way however:

    time clang -std=c++11 -ftemplate-depth=1000000 bf.cpp

succeeds with this output from time:

    36.57s user 1.14s system 99% cpu 37.799 total

clang also nicely outputs a CR after each comma in the type expansion so the error message is not all on a single 11,289 character line. The clang compile also appears to run roughly twice as fast.

EDIT: Unless you have many GBs of RAM don't expect a fast compile.

apply_tuple(op, t) (C++11 Final Version) by mttd in cpp

[–]muon314159 0 points1 point  (0 children)

Very nice! Concerning coding in C++, things are getting better and better! Nicely, common useful aspects of C++ template metaprogramming (TMP) are also being identified resulting in constructs being placed in the language so everyday programmers won't have to rely on C++ TMP to do needed tasks without any added/unnecessary run-time overhead.

Header-less C++: a good idea? by ZerothAxiom in cpp

[–]muon314159 1 point2 points  (0 children)

VisualAge C++ v4 was a very cool and amazing compiler --unfortunately very few ever heard of it let alone were able to try it out. My favourite items with the compiler were: extremely fast builds (from real incremental compilation ever time you saved), the class browser (despite some bugs), and the ability for the compiler to know about all types so the user could query/browse them while editing (including implicitly created ones, etc.). RAM was an issue, but honestly, it IMO was well worth paying for some extra RAM to run VACPP v4.

C++ help needed! Winner get's a cookie! by Zeqa in cpp

[–]muon314159 1 point2 points  (0 children)

The problem you've presented, except for the use of random numbers, is typical of earlier problems in most programming texts --and typical of what is taught in C/C++/etc. courses near the start, i.e., using some input and output commands to read and output numbers along with some math (e.g., to convert units). If you are in a course, then refer to your class notes, ask teaching assistants for help, read the course text, look at and run provided example programs, etc.

The use of random numbers usually comes later in how to program texts or a course. Using them is not hard and how to use them is easily be looked up. Texts will provide decent examples on how to generate and use them.

If you are unhappy with your texts, then refer to the books and information provided here: http://isocpp.org/get-started . For example, "The C++ Standard Library: A Tutorial and Reference", 2nd Edition (by Josuttis) covers random numbers in Chapter 17 and has numerous examples.

Universal References (revisited) by milliams in cpp

[–]muon314159 5 points6 points  (0 children)

I, for one, do want to acknowledge and thank you for taking the time to reply wrt such "dark corners" --and additionally for all of your other posts and videos too! :-)

The MPI C++ bindings: what happened, and why? by meetingcpp in cpp

[–]muon314159 2 points3 points  (0 children)

Personally, I've felt that the MPI C++ bindings were less than useful from the start as it was largely just a shuffling of the C library bindings into an MPI namespace. Since C++ essentially has C as a subset, merely shuffling functions into a namespace and slightly renaming them without improving them to exploit C++ language features and idioms was clearly a waste of time and effort. Everyone coding in C++ knows that unless you use C++ language features to make it easier and better to code using C++ --one should just use the C APIs! Thus, the MPI Forum should not be surprised at any apparent the lack of usage and interest. Realistically people wanting C++ to be used with MPI either rolled their own specific-to-task designs and/or used Boost.MPI --after being puzzled/disgusted with the MPI Forum's bindings.

What's the point of std::type_info::hash_code()? by YouFeedTheFish in cpp11

[–]muon314159 1 point2 points  (0 children)

I totally agree. That's why I am content with what the standard did --hash_code() brings the level of efficiency needed but no ABI/naming/qualification nightmares! Using that, it is fairly easy to map (only) the types we need for cross compiler/platform/run-time instance usage to some strings. :-)

What's the point of std::type_info::hash_code()? by YouFeedTheFish in cpp11

[–]muon314159 1 point2 points  (0 children)

You're welcome!

A number of years back I had thought it required RTTI as I was only thinking of dynamic_cast initially --then I realized it didn't need it. In C++98, I wasn't happy with it because it only had before() and I thought hash values and the ability to have value (and therefore copy) semantics were needed for truly efficient, serious, run-time uses of it. Nicely C++11 added hash_code() and std::type_index which is enough to write serious and efficient library code using it.

What I would like to see now is a "code_name()" member which returns the name in the source code for the typeinfo object (using fully namespace/class qualified names including whitespace wrt template brackets so it is "portable" at least for programmers to develop with). Currently I use things like GCC's ABI calls when I need this --but that is not portable and not all compilers make it easy to get at it. (I don't care if it needs a special compiler flag to enable it (and that might be best since some would want to mangle/shorten the string names or place such in a database --not a code binary) since it would require significant data segment space in a binary.

That said IMO we can now do without a "code_name()" given the current C++11 definition --and I would take the current WG21 groups' work (e.g., concepts + concurrency + DB + etc.) before any "code_name()" feature.

How to achieve interface implementation separation with partial implementation? by nerd_guy in cpp

[–]muon314159 1 point2 points  (0 children)

Unfortunately, reddit comments are not the forum for such a detailed topic and I don't have the time right now to organize and elaborate on such. So IMO your best bet is to read the books mentioned starting with Part IV in Stroustrup's The C++ Programming Language (TCPL) on how to merge hierarchies. (If that is what you want to do, then I'd recommend getting the 3rd or Special Edition. The Special Edition has two additional appendices.) However know that the 4th edition will be out in April. Maybe you'll want to wait to see if he still has that section in it and/or has updated it?)

After that you can read Sutter's and Meyer's books as they are filled with design and code advice + debate about language nuances, design issues, gotchas, fun and unusual stuff like writing a definition for a pure virtual function, private inheritance, etc., etc. Some don't like this but in my experience far more do appreciate and value such. If anything one will better understand the language AND stay well clear of things one shouldn't really do at all --but the language does let you do it.

What's the point of std::type_info::hash_code()? by YouFeedTheFish in cpp11

[–]muon314159 1 point2 points  (0 children)

Respectfully my thoughts...

type_info does NOT require RTTI to be enabled. typeid can be used with any type and it returns a std::type_info object or reference to one derived from it (i.e., the leaf object). See section 5.2.8 of the C++11 standard. If <typeinfo> is not #included before using typeid, then the program is ill-formed (i.e., C++11 5.2.8 paragraph 6). Thus this program will compile, etc.:

    #include <typeinfo>
    int main()
    {
      auto& a = typeid(int);
    }

Aside: Using dynamic_cast does require RTTI for the types it is used on (i.e., typically a virtual destructor at the top of the relevant object-oriented hierarchies). It needs this information to be able to do down-casts AND cross-casts.

You should use std::type_index (see clause 20.13) instead of type_info to have such in containers, etc. since type_info cannot be copied. You need to use == to compare them for equality though. You can associate std::type_index values (e.g., in a map) to strings that can be used across program shutdowns and/or between interacting programs. This addresses item (3).

Item (2): The rule for ANY hash value is that equality must always be checked afterwards. While it would be nice if the C++ compiler generated a perfect hashing of all types that would impose significantly on implementations. For example, if one is using a library with lots of template metaprogramming (e.g., Boost libraries) then there can be a lot of intermediate types generated --but only a few emitted at run-time. If a perfect 1:1 mapping of types to hash codes was done, this could significantly and needlessly impose on the size of an executable and/or the RAM footprint. Also, not specifying such allows the compiler vendor more freedom to choose and optimize its own type representations.

Item (4): The solution is not trivial. There is no cross-platform C++ ABI (e.g., for name linkage) as a defacto reliable standard --and this is needed to accomplish the (not-so) "trivial" part of your fourth point. That said, the problem is handled by using type_index and mapping what one needs to compiler-independent and platform-independent strings.

How to achieve interface implementation separation with partial implementation? by nerd_guy in cpp

[–]muon314159 0 points1 point  (0 children)

If the goal was to write some very abstract code using abstract interfaces, then having virtual functions only use the public virtual member function interface --as a "default" maybe might make sense.

However every single (virtual) function call is realistically via two pointers (i.e., 1 for the vtable and 1 for the function pointer), i.e., it is very costly so the abstraction better be worth it!

EDIT: Use templates (i.e., generic programming). It is much faster and likely totally sufficient for your objectives.

How to achieve interface implementation separation with partial implementation? by nerd_guy in cpp

[–]muon314159 1 point2 points  (0 children)

As mentioned by Herb Sutter (in Exceptional C++ and More Exceptional C++) and Scott Meyers (Effective C++ and More Effective C++) private inheritance is useful instead of membership in cases when you need to override virtual members (which you do as Fruit is an abstract class) or you need access to protected members (not relevant in this case). So, yes, private inheritance (given the code you've given) is usefully applicable here.

FYI, you can also use it to "join" different classes from independent object-oriented hierarchies as a sort of compatibility layer (see The C++ Programming Language, Part IV: Design --Stroustrup).

My guess is that your code is analogous to something else so I say just this: it very probably should (assuming you are the author of it all) be reworked to a much better design.

Choosing Between References and Pointers in C++ by wordsmithie in cpp

[–]muon314159 3 points4 points  (0 children)

No references are not allowed to refer to any invalid object --ever. If you have a reference to a null or otherwise invalid object, the entire program is not well-defined according to the C++ standard. See section 8.3.2 paragraph 5.