2008-06-11
Merkel und die Stasi
Eigentlich wollte ich ja in dieser Kategorie nichts mehr bloggen. Vor allem fefe's blog liefert dazu mehr als genug. Diese Geschichte erachte ich allerdings als Meilenstein auf dem Weg in die Aristokratie.
Es gibt Unterlagen, die den Schluss nahelegen, dass die Kanzlerin Angela Merkel eine Stasi Mitarbeiterin war, wie die schweizer Presse berichtet.
Und Angela Merkel hat die Macht, eine deutsche Berichterstattung über ihre mutmaßliche Stasi Vergangenheit zu unterbinden.
Das zeigt mir:
- die deutsche Presse ist hinreichend gleichgeschaltet.
- eine parlametentarische Opposition existiert in Deutschland nicht.
- die Demokratur funktioniert.
2008-06-11
default arguments and name lookup
from fefe's blog two C++ gotchas about default arguments and name lookup rules.
2008-05-26
template type arguments
To gain code locality I often use local types. I really like this feature as it allows me to define a type a the location where it is needed.
A frequent use for this would be compare or ordering functors
for standard algorithms like sort or standard
containers like hash_maps. This look's like this:
Other languages have code blocks or other features which allow you to write the sort criteria straight away. Local types are an tolerable alternative to this in my eyes.void foo(const std::vector<Bar> bars) { struct Sort { bool operator()(const Bar& lhs, const Bar& rhs) const { /* ... */ } }; std::sort(bars.begin(), bars.end(), Sort()); }
Ähm, I mean, they could have been. But the standard prevents this. Section 14.3.1.2 says:
A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
Oh my nudels. Why? Does anybody know a good reason for this? I can't imagine any. Furthermore I wonder how the syntax would look like when using an unamed type as a template parameter.
To make the confusion complete the GNU C++ compiler (version 4.2.3) dumps the following error when compiling the above example.
error: no matching function for call to 'sort(__gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, __gnu_cxx::__normal_iterator<Bar*, std::vector<Bar, std::allocator<Bar> > >, foo(std::vector<Bar, std::allocator<Bar> >&)::Sort&)'Yeah, right.
2008-05-26
anonymous classes
Recently I tend to group semantically related members into nested classes or structs. For instance imagine a class with concurrent access:
class Foo { public: int getSomething() { Lock l(purpose.mutex); return purpose.something; } private: struct { Mutex mutex; int something; } purpose; };
To avoid redundancy I don't name such nested structs. Why should I? C++ provides the feature of anonymous classes and structs and this technique is a good example why one would like to have it.
But as often with C++ this language feature collides with others and makes it less usable. In this case you are getting problems when the grouped members need to be initialized. As a constructor must have the name of the class anonymous classes can not have constructors.
Orthogonality must definitly be a design goal for usable general purpose languages. And this property is greatly missing in C++ which is the matter for my blog entries.
2008-05-26
signed or unsigned
I'm programing in C++ for years now and I still experience frequent surprises. Even on topics where I was dead sure.
Is an int signed or unsigned? The standard clearly
says (section 3.9.1.2)
There are four signed integer types: "signed char", "short int", "int", and "long int."So writing just int means the same as signed int which is as expected.
And here is the surprise: this is not always true. Section 9.6.3 says:
It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int or long bit-field is signed or unsigned.
Unbelievable... It would have been too easy otherwise, I guess...
Thanks, Roker
2008-05-26
ain't a typedef
typedefs are a convenient way to give semantics to
variables and to stay flexible for future adjustments of the actual
used type.
For example if you deal with navigation software you might have
some typedefs for Direction and Speed
which could be simply ints. And you might have a
typedef for Position which is a
std::pair<int32_t, int32_t> so that all valid
GPS positions of some required resolution can be represented.
Say you want to have some toString or
operator<< methods for debuging purposes. So you
could have a call trace of your program like this.
and get an output like thisstd::ostream& operator<<(std::ostream& oss, Direction direction) { oss << "Direction=" << int(direction) << " degree"; return oss; } std::ostream& operator<<(std::ostream& oss, Speed speed) { oss << "Speed=" << int(speed) << " mps"; return oss; } void someFunction(Speed speed, Direction direction) { logger << "someFunction(" << speed << ", " << direction << ")"; //... }
someFunction(Speed=23 meter/second, Direction=42 degree)
Looks good, but doesn't work. If Speed and
Direction are typedefed to the same or
implicitly castable types the problem manifests:
error: ambiguous overload for 'operator<<'
Unfortunately, altough the keyword is named typedef
it is no type definition. The standard says in section 7.1.3:
A typedef-name is [...] a synonym for another type. A typedef-name does not introduce a new type the way a class declaration [...] or enum declaration does.
Prohibition of use of function overloading techniques is just one aspect of the problem. In general you have a type with different semantics but you can not treat it differently. This is a frequent source of annoyance.
PS:
Yes, int32_t is not part of ISO-C++. And this is a
mistake...
2008-05-05
tell me why!
Most C++ quirks can be argued by efficency or inheritence reasons. But sometimes I just don't see why there is yet another exception in the rules of the language. Such an example is the initialization of static constant data members:
Section 9.4.4 of the ISO standard says:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression.
Here is an example of this:
class X {
static const int i = 23;
};
Now, I wonder why this in-place initialization is restricted to those two types. I would like to be a able to express:
class A;
class X {
public:
static const A* special_meaning=0;
void do_something(const A* with=special_meaning);
};
C++ prevents me from writing descriptive code in this case. And for
what reason? I can't see any.
By the way, section 9.4.4 adds:
The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.Sure, linker and such... So what is this in-place initialization good for after all?
Thank you, Liesa
2008-05-05
scope jumble
What's the value of X::i?
int g() { return 23;}
struct X {
static int g() { return 42; }
static int i;
};
int X::i = g();
The answer is: 42 - says ISO C++ in section 9.4.2. The initialization of the static data member is implicit in the scope of the struct. Oh, yes! The standard's example is even more fun:
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
Note that X could be definied in another header file
than g and that the initialization normaly is in a
cc-file. Find, Rover, find!
Thank you, Roker

