Clang getting involved

Hi all.

I'm russian student from Moscow. I like C++ and
I would like to contribute to Clang not as part
of GSOC. I have already contributed to Boost.Math.

I wanted to implement a static if declaration as
an extension proposed by Herb Sutter, Andrei Alexandrescu
and Walter Bright here
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3329.pdf

This feature is used in D language.
But I don't know how it is relevant in Clang. Also I have
just found some problems. For example, I don't know
how better to represent it in AST: either as Decl or as Stmt.
If (static if) is Stmt, it is easier to implement many things
just using similar functions for if-statement.

Maybe somebody has better ideas. I will be glad to any advices.
Sorry for my English.

Best regards,
Anton.

Hi all.

I'm russian student from Moscow. I like C++ and
I would like to contribute to Clang not as part
of GSOC. I have already contributed to Boost.Math.

I wanted to implement a static if declaration as
an extension proposed by Herb Sutter, Andrei Alexandrescu
and Walter Bright here
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3329.pdf

FYI Stroustrup shot that feature down pretty hard <
http://isocpp.org/blog/2013/03/n3613-static-if-considered>. It may not be
the best one to implement.

-- Sean Silva

FYI Stroustrup shot that feature down pretty hard

<http://isocpp.org/blog/2013/03/n3613-static-if-considered>. It may not be
the best one to implement.

Yes, I know. But I hoped to see it like an extension. Just interesting, can
it be helpful?

Hello,

FYI Stroustrup shot that feature down pretty hard

<http://isocpp.org/blog/2013/03/n3613-static-if-considered>. It may not be
the best one to implement.

Yes, I know. But I hoped to see it like an extension. Just interesting, can
it be helpful?

FWIW: Clang supports Microsoft's __if_exists extension when in VisualC++ mode:
<http://msdn.microsoft.com/en-us//library/x7wy9xh3.aspx> It is similar (although
more restrictive) to "static if".

I'm not sure if a clang-specific language extension would be accepted into clang,
although it could be used to evaluate the usefulness of "static if". But then
I'm biased as I'd very much like "static if" to become part of the C++ standard;
even though it's viral, as Stroustrup writes, it would reduce the need for helper
templates.

Jonathan

The big problem with 'static if' is that it's three different features that
have got muddled together. Those are:

1) A static if, just like #if, where the condition must be a non-dependent
constant expression, and the body can be arbitrary brace-balanced token
soup. This basically just allows more advanced constants in #ifs.

constexpr bool has_interval_literals() { return
__has_feature(interval_literals); }
static if (has_interval_literals) {
  static_assert( [1...4) + [4...6] == [1...6], "" );
}

2) A template if, that introduces a separately-instantiable template entity
(and thus introduces a scope). As is usual for templates, the body must be
instantiable for some template arguments (it can't be token soup).

3) An enable if, that makes declarations visible or invisible depending on
some predicate.

Of these:
- the first isn't hugely useful, since a lot of the "interesting" compile
time constants for this sort of check are preprocessor constant expressions
too, so #if works,
- the second is already possible using generic lambdas (but it's a little
hacky):
  if_(b, [&](auto){ blah; }, [&](auto){ blah2; }) // implementation left as
an exercise to the reader
- the third is already somewhat possible (using clang's attribute
enable_if), and will be standardized through the concepts effort.

People sometimes want to mix these possibilities (and in particular, use
the 'token soup' model in a template), but that's essentially incompatible
with the tree-transformation model that is used for template instantiation
by at least Clang and GCC. Given our current state, I think the only thing
worth pursing is #1, and I don't think it meets Clang's criteria for
language extensions.

Hello,

The big problem with 'static if' is that it's three different features that have got muddled together. Those are:

1) A static if, just like #if, where the condition must be a non-dependent constant expression, and the body can be arbitrary brace-balanced token soup. This basically just allows more advanced constants in #ifs.

constexpr bool has_interval_literals() { return __has_feature(interval_literals); }
static if (has_interval_literals) {
  static_assert( [1...4) + [4...6] == [1...6], "" );
}

2) A template if, that introduces a separately-instantiable template entity (and thus introduces a scope). As is usual for templates, the body must be instantiable for some template arguments (it can't be token soup).

3) An enable if, that makes declarations visible or invisible depending on some predicate.

Of these:
- the first isn't hugely useful, since a lot of the "interesting" compile time constants for this sort of check are preprocessor constant expressions too, so #if works,
- the second is already possible using generic lambdas (but it's a little hacky):
  if_(b, [&](auto){ blah; }, [&](auto){ blah2; }) // implementation left as an exercise to the reader

Maybe I'm misunderstanding something, but when I as a reader tried your exercise, I failed
miserably at first:

#include <type_traits>

template <bool Expr_>
struct StaticIf {
  template <typename Code_>
  static void apply(Code_)
  {
  }
};

template <>
struct StaticIf<true> {
  template <typename Code_>
  static void apply(Code_ code)
  {
    code(1);
  }
};

template <bool Expr_, typename Code_>
void static_if(Code_ code)
{
  return StaticIf<Expr_>::apply(code);
}

template <typename T>
void foo(T t)
{
  // Call <t.bar> if <T> is a class
  static_if<std::is_class<T>::value>([&](auto) {
    t.bar();
  });
}

struct Bar {
  void bar() {}
};

int main()
{
  foo(1);
  foo(Bar{});
}

This does not compile as <t> inside the generic lambda is not a name dependent on the lambda's
template parameter and thus requires <T> to be a class with a method <bar>.

It is of course possible to make <t> artificially dependent on the lambda's template parameter,
e.g. by saying:

// Make T dependent on D
template <typename T, typename D>
T makeDependent(T t, D /*d*/)
{
  return t;
}

template <typename T>
void foo(T t)
{
  // Call <t.bar> if <T> is a class
  static_if<std::is_class<T>::value>([&](auto dummy) {
    auto t2 = makeDependent(t, dummy);
    t2.bar();
  });
}

This compiles, but IMO is really hacky and inelegant. Similar to local structs are inelegant
compared to lambdas.

Do you know of a more elegant way?

Jonathan

P.S: Correct forwarding of values left as an exercise to the reader :wink: