14

Consider the following case

typedef void (*foo)();
template<foo f>
struct bar {
     static_assert(f!=nullptr,"f == null!");
};

void baz() {}
inline void bax() {  }

bar<baz> ok;
bar<bax> bad; // error: non-constant condition for static assertion

Both baz and bax are accepted as template arguments. It indicates that both are accepted as constants. However, at static_assert they appears to be different (at least in gcc 4.9) - bax is not a constant anymore.

My assumption was that static_assert and template evaluate constantness identically. E.g. either error should be

  • 'bax is not a valid template argument' or
  • static_assert should not raise non-constant condition error.

Am I wrong?

Top-Master
  • 7,611
  • 5
  • 39
  • 71
hutorny
  • 863
  • 11
  • 17
  • 1
    Unless `foo` is declared somewhere, I expect this won't compile at all... – Mats Petersson Aug 17 '15 at 07:39
  • fixed, lost typedef void (*foo)(); added – hutorny Aug 17 '15 at 07:44
  • 1
    VC++ 14.0 accepts both. –  Aug 17 '15 at 07:46
  • 2
    [Works fine for me](http://coliru.stacked-crooked.com/a/d4542a0bf5217a42). – Quentin Aug 17 '15 at 07:46
  • @πάντα ῥεῖ - in other instantiation of bar in could: bar nill; – hutorny Aug 17 '15 at 07:47
  • 2
    @Quentin: not with gcc... http://coliru.stacked-crooked.com/a/72fd4b666aa73737 – Karoly Horvath Aug 17 '15 at 07:49
  • 7
    Works in clang++ 3.7 [about a week or two prior to 3.7-RC1], not in gcc 4.9.2. Suspect that it's a gcc bug. – Mats Petersson Aug 17 '15 at 07:50
  • The only difference I see in the standard is that a template argument accepts _converted constant expression_. (5.20.4.: "A _converted constant expression_ of type `T` is an expression, implicitly converted to type `T`, where the converted expression is a constant expression and the implicit conversion sequence contains only (...) such expressions may be used in `new` expressions, as case expressions, as enumerator initializers if the underlying type is fixed, as array bounds, and as non-type template arguments.") – Tomasz Sodzawiczny Aug 17 '15 at 09:51
  • There is no way that a template value parameter is not a compile time constant, and comparing such a pointer to `nullptr` should be a constant expression. If the standard actually agrees with gcc, this is just a sign there is a defect in the standard that gcc should be ignoring anyhow. – Yakk - Adam Nevraumont Aug 17 '15 at 17:28
  • 3
    Is this [GCC bugzilla thread](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52036) related to this problem? Clang3.6 can compile the code in the bugzilla, but gcc5+ and gcc6HEAD can't do. – akakatak Aug 25 '15 at 18:36
  • g++ 4.7.2.5 return an error. `non-constant condition for static assertion` which I believe is the correct behavior – Jens Munk Sep 10 '15 at 21:14

2 Answers2

1

Just yet another GCC bug, update to newer version, or migrate to LLVM (clang).

See issue ticket for details:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52036

Top-Master
  • 7,611
  • 5
  • 39
  • 71
-1

When a function is inlined, the pointer to the function does not exist. So we can not compare it with nullptr.

Whether a function is eventually inlined or not, depends on the compiler. inline keyword does not guarantee that.

Alexander Lobov
  • 386
  • 2
  • 11