On Saturday, 9 March 2013 at 14:49:36 UTC, d coder wrote:
Greetings
I believe the paper takes a contrived route to criticize
"static if". It takes some bad code examples which are not
obvious use cases of "static if" and then goes on to say that
the resultant code is not good. I think the code example to
begin with was not good.
Agreed. Just barely started reading it and it appears they're
nit-picking about something they would have trouble with if it
was scoped or not, but more importantly they aren't considering
something we would do automatically. If you declare in one, you
declare in the other, only difference may be a few details like
storage types, removing some of the problems entirely; So he's
attacking something that could be done in the preprocessor
anyways; Or maybe he's attacking bad coding style but isn't
expressly saying it?
[quote]
Conditional compilation, the selective inclusion of statements in
a translation unit, is a conventional example. Consider a simple
example of introducing some declarations, depending on whether
the size of some type, T.
static if (sizeof(T)==8) {
void fun();
void gun(int);
} else {
void gun();
typedef tx int;
}
The semantics of the program are this: if sizeof(T)==8, the
compiler will parse the statements in the “then” branch, and will
tokenize and brace-match the declarations in the else branch.
Those other declarations would be uninterpreted by the compiler.
Note that unlike normal if statements, the braces enclosing the
conditionally compiled statements do not introduce a new scope.
Those declarations are declared into the scope enclosing the
static if block. This difference makes
code written using static if harder to read and
understand—modulating between static and non-static ifs in a
single block provides ample opportunities for confution and
mistakes.
The effect of this declaration is to conditionally modify the
current scope with a set of new declarations. How can we know,
later in the program, which version of gun we should use, or
whether tx is defined or not? Any use of those
declarations would also need to be wrapped.
static if (sizeof(T)==8)
gun(32);
else
gun();
static if (sizeof(T)==8) {
long n = x;
}
static if (sizeof(T)!=8) {
tx n = x;
}
Thus, the use of static_if for conditional compilation is viral.
The impact of conditional parsing on program analysis tools is
substantial. While the feature may be easily implemented as part
of the translation process, program analysis tools have
traditionally struggled with conditional declarations. The
inclusion of multiple variants (via, e.g., preprocessor
conditions) and simultaneous repersentation within a single
program model is still an open problem in the source code
analysis communities. Adopting static if will make analysis
harder, not easier.
[/quote]
And I'm sure that using the preprocessor keeps things simple
right? Geez let's take a C/C++ version of that... Preprocessor
tokens may be off, but the point should get across... :P
#ifdef X
void fun();
void gun(int);
#else
void gun();
typedef tx int;
#endif
And
#ifdef X
gun(32);
#else
gun();
#endif
#ifdef X
long n = x;
#endif
#ifndef X
tx n = x;
#endif
[quote]
We have already heard suggestions of static_for and static_while.
Can static_switch be far behind? C++ would become a low-level,
unprincipled hackers’ favorite playground. In our opinion, if you
want compile-time computation, look to constexpr, which does have
a sane and typesafe underlying model.
If we do not provide a static_for, hackers will simply make one
out of static_if or fake equivalents.
[/quote]
C++ is just as low level as C, this statement is useless. Being
against 'static_for' is kinda dumb since if you think about it,
it just unrolls the loop ahead of time instead of optimization,
other than that it shouldn't do anything odd. I'll agree not to
add static_for only because it's not really needed.
[quote]
The semantics of static_if are to tokenize the branch not taken.
If the condition is dependent, as it is in the statements above,
then the compiler must not parse either branch. Both branches are
tokenized since either one could
contain compiler-specific extensions—or both, or neither. That
won’t be known until both branches would have been fully parsed.
<snip>
Consider the real world impact of this design choice. The
inability of the compiler to parse the branches of the compiler
means that the library writer will need to instantiate every
branch of the template just to ensure that the syntax is correct
and that no spelling errors have been made. Today, this is done,
to a large extent, by the compiler
[/quote]
In C++ you need to have EVERYTHING loaded (declarations, etc)
loaded before you can compile anything, Unlike in D where all
tokens effectively have one meaning as intended, so the whole
template issues aren't an issue. Seems like they're just opening
their own cans of worms :P
[quote]
The trailing if clause enforces a requirement that T must be
convertible to the value_type of I. We most strongly agree that
some mechanism is needed for constraining templates, this is
particular syntax leaves much to be desired.
It is particularly verbose, and leaves the entire body of the
template unchecked. The body must only be tokenized because the
static condition could guard the instantiation against
compiler-specific extensions in the nested code. That fact would
only be ascertainable after the entire body is parsed.
[/quote]
Deja-vu, until recently (C++11) when they changed 'auto' to
accept any type didn't they have to be super verbose everywhere
anyways? Verboseness shouldn't matter in templates so much as
it's user code that needs to be clean. Microsoft core teams admit
their STL they write and maintain is ugliest and basically
illegible to anyone outside the team; Although template structure
as C++ is and their STL doesn't help much.
[quote]
The static if feature might also be used to support overloading.
Below is an implementation of advance.
<snip>
Because static if only allows for Boolean decisions, overloading
on a set of overlapping constraints requires the programmer to
write bounding predicates like those above (e.g., input iterator
but not bidirectional, bidirectional but not random access,
etc...). This model of overloading is brittle, error-prone,
verbose, and defines a “closed world”. No other overloads may be
considered without modifying the constraints on the existing
declarations in order to ensure consistency.
Declarations might be condensed using else clauses, but this is
only cosmetic.
[/quote]
*gasp* Walter! Did you know static if only allows boolean
decisions! My god our static if MUST is be error-prone and
brittle, a 'closed world'!
*Note sarcasm*
I'll agree a modification for handling nested static if's or
something could be nice, but it's not unmanageable if you keep it
relatively small. Hell what am I talking about? People go above
and beyond a language to do stuff I wouldn't even consider, like
a full x86 emulator in JavaScript..
[quote]
The use of static if might also be used to reorder data
structures for tighter alignment, but this is a potentially
dangerous idea that could lead to bugs that are exceptionally
difficult to diagnose and fix.
[/quote]
Doesn't he mean the pre-processor?
#define max(x,y) x > y ? x : y
int a = 1, b = 2;
z = max(a++, b++);
struct X {
#ifdef TIGHT
int x;
char y[100];
#else
char y[100];
int x;
#endif
}
The largest complaint he has is managing tokens and being able
to figure out what is what; In short previous bad decisions on
the language HE HIMSELF MADE are preventing potential growth of
the language making static if in his mind, unmanageable, yet you
can do anything with the preprocessor (well, no CTFE...).