flyx.org

Personal homepage of Felix Krause

On Having Problems

Variations on

You have a problem and decide to use regular expressions.
Now you have two problems.

Inspired and partly copied from [1], [2] and [3].


You have a problem and decide to use Java.
Now you have a ProblemFactory.

You have a problem and decide to use Python.
Now you have something that looks, swims and quacks like a problem.

You have a problem and decide to use binary.
Now you have 10 problems.

You have a problem and decide to use floating points.
Now you have 1.00000000000001 problems.

You have a problem and decide to use Apple.
Now you have a shiny problem.

You have a problem and decide to use threads.
Now have a you problem.

You have a problem and decide to use mutexes.
Now you

You have a problem and decide to use LISP.
Now you have a list of problems.

You have a problem and decide to use asynchronous calls.
Now you wait for having a problem.

You have a problem and decide to use Smalltalk.
Now you have a metaproblem.

You have a problem and decide to use an unchecked cast.
Now you have a solution and it is Segmentation Fault.

You have a problem and decide to use JavaScript.
Now you have 3 problems in Firefox, 5 problems in Safari, 2 problems in Chrome, and 11 problems in Internet Explorer.

You have a problem and decide to use a sandbox.
Now you still have a problem but you don't care.

You have a problem and decide to write a Makefile.
Now you know how to make problems.

You have a problem and decide to use anagrams.
Now you have lamb rope.

You have a problem and decide to use Unicode.
��� ��� ���� � �������.

You have a problem and decide to use STL.
Now you have a _Hashtable_iterator<std::pair<const basic_string<char, str::char_traits<char>, std::allocator<char> >, int>, basic_string<char, std::char_traits<char>, std::allocator<char > >...

You have a problem and decide to use pair programming.
Now you have someone else's problem.

You have a problem and decide to google it.
Now you know 31,457 ways to describe your problem and around 15 completely wrong solutions for it.

You have a problem and decide to upgrade to paid version.
Now you have an Ultimate Pro blem.

You have a problem and decide to use Agile.
Now you have an epic problem.

You have a problem and decide to use Haskell.
Now you have a lazy problem.

You have a problem and decide to use Maven.
Now you have a problem snapshot.

You have a problem and decide to use JPA.
Now you have a persistent problem.

You have a problem and decide to use crowd sourcing.
Now it's their problem.

You have a problem and decide to use Scala.
Now you have problem traits.

You have a problem and decide to use Prolog.
Now there exists a person that has at least one problem.

You have a problem and decide to use static code verification.
Now you can prove that you have a problem.

You have a problem and decide to use SQL.
Now you have two problems but you can join them.

You have a problem and decide to use -Wall.
Now you have a problem and 21 warnings.

You have a problem and decide to use Visual Basic.
Now you resume next.

You have a problem and decide to use Visual C++.
Now you have a ?Problem@@YAXHD@Z.

You have a problem and decide to use Splash.
But nothing happened.

You have a problem and decide to use ZSH.
Now you have a pro<TAB>

You have a problem and decide to use LaTeX.
Now you have a problem, perhaps a missing \item.

You have a problem and decide to use Debian.
Now you have a problem, a problem-common and a problem-dev.

You have a problem and decide to use XML.
Now you have a <problem xmlns="http://problem-working-group.org/schemas/2015/problem">

You have a problem and decide to use Ada.
Now you have a rendezvous with your problem.

You have a problem and decide to use PHP.
Now you have a problemsolve(). Or a problem_solve(). Or a problem_real_solve(). You're not sure.

You have a problem and decide to use CoffeeScript.
Now you've had a problem before it was cool.

You have a problem and decide to use C++ metaprogramming.
Now you have a partial problem specialization.

You have a problem and decide to post it on StackOverflow.
Now you have a favorite problem.

You have a problem and decide to use Perl.
Now you have a comprehensive problem archive network.

You have a problem and decide to use tips at startup.
Did you know that you have a problem?

Tags: programming fun

Reasons why C++ sucks

Disclaimer: This list is not and will never be complete (but I may update it if I'm bored). It also contains strong language.

Preprocessor

  • Yeah, it has a fucking preprocessor. The preprocessor is a feature of C because C lacks so many features that the preprocessor is needed. Nobody cared to include tools in C++ to make the preprocessor obsolete, so it still lurks around and takes your firstborn children.
  • You still use the preprocessor to include headers. So if you have a syntax error in one header, let's say, a missing semicolon in the last line, the compiler complains giving a line in a completely different file. The proper way to do it would be to parse headers separately before including them.
  • Oh, and because you still have to use #include, you obviously need those shitty #ifndef guards in every fucking header file. Yeah, if you have a fancy compiler, you can use #pragma once. Well, unless the gcc guys decide to deprecate it.

Type System

  • C++ has a bool type. It is the most idiotic boolean type you will ever see. Firstly, you can use any integral type in a place where you need a boolean value. This leads of course to programming errors like if (i = 2). But if you actually decide to use the bool type, you run into funny stuff, for example: An uninitialized bool variable may be neither true nor false - depending on your compiler, if you define bool a;, both a and !a may evaluate to true.
  • Enums are really dumb. Take for example:

    enum traffic_lights {
        RED     = 1,
        YELLOW  = 2,
        GREEN   = 4
    };
    

    As you may expect, this is just an int with some named constants. You can declare multiple values with the same value, you can assign int value to it. And if you do YELLOW++, you don't end up with GREEN, but with a value that isn't defined in the enum (but doesn't raise an exception either). You also cannot iterate over existing enum values. At this point, this is just useless syntax sugar for

    #define RED    1
    #define YELLOW 2
    #define GREEN  4
    
  • Oh, did you know, C++11 does introduce enum class. It fixes none of the issues described above, but makes you prefix the enum values with the name of the enum. Well done.

  • Strings are still C strings. Yeah, you may have heard of std::string, which is a type that is somewhat better than a raw char*, but the problem is, string literals are still char*. They get converted to std::string in some places, but it does not work everywhere. For example, this doesn't compile: "a" + "b".

  • Typedefs everywhere! If the error message of a compiler (at least gcc) mentions for example std::string, it does not output std::string, but std::basic_string<char>, because it's a typedef. This gets really ugly with more complex types.

Functions

  • Function parameters are mutable by default. This is bullshit. The usual case is that you don't want to modify a function parameter, because they are passed by value and won't be copied back. It is also horribly inconsistent: Reference type parameters (those with myriads of & around them) are actually always const (that is, you cannot change the reference, but you can change the referenced value).
  • Functions that don't have void as return type are not required to return a value. Seriously? This just screams for bugs if someone somewhere forgets to write return result; and the compiler doesn't remind him.

Templates

  • You have to put the complete implementation into the header. This slows down compilation considerably, because all the fucking implementation of the fucking template is parsed every fucking time it is fucking used. Oh, you can of course try to use precompiled headers and open the door to hell.
  • You can use the keywords typename and class for template parameters, and they do exactly the same. You can put a class into a typename parameter, and you can put a non-class into a class parameter. So what's the point?
  • If you use a template parameter for defining a type within the template implementation, you often have to put typename in front of it. Example:

    template<typename T> a() {
       typename std::vector<T>::iterator t;
    }
    

    It wouldn't compile without the typename. And if you miss it, the compiler will probably give you an error that is extremely hard to understand. If you get some huge error message when compiling a template implementation, add more typename.

  • You cannot constrain type parameters. For example, you cannot declare that a type parameter has to be a child class of some other class. You just assume random things about the template type, and if someone else uses in a way you didn't plan for, he may get error messages pointing to the implementation of your template. There was a feature called Concepts that was planned for C++11, but it was dropped (and may come in C++14).

  • Support for value parameters is very limited. For example, you cannot declare a template taking a parameter of type std::string. You can declare a template parameter of type char*, but you cannot directly pass a string literal to it. You have to define a char* constant with external linkage somewhere and use that as template parameter.

Object Orientation

  • this is a pointer. Why isn't it a reference? It may never be null, and if it is, your code is broken anyway.
  • The compiler generates some methods of a class automatically based on complicated rules. Examples are the assignment operator, a copy constructor and such. You can also instruct the compiler to not generate these methods if they would be automatically generated. Some of these methods are needed for using the class in the standard container structures like std::vector, so you have to check all this stuff every time you declare a class.

Standard Library

  • The smart pointers (std::unique_ptr et. al.) are a sorry excuse for a missing language feature. A class usually has no idea about whether it is accessed with a smart pointer or not, but when it passes a reference to itself somewhere, it needs to know. So you suddenly have to derive from std::enable_shared_from_this to be able to convert this to a smart pointer.
  • Iterators are simply a huge mess. To implement a custom iterator, you kind of need the iterator module from the Boost library if you want to have it done till the end of the year, and even that is really complicated to use.

Tags: programming