Please part me if the summary isn't so informative. Can't put what's on my mind in a few words. So my system info is: gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Linux 3.2.0-34-generic-pae #53-Ubuntu SMP Thu Nov 15 11:11:12 UTC 2012 i686 athlon i386 GNU/Linux Consider the next code snippet: template <int X> struct DivByX { enum { value1 = X, value2 = int(100.f / value1) }; }; enum { valueA = 0, /// False branch in the condition should never be taken into account. /// And moreover, template should be constructed. valueB = (/* Always false >>>*/1 > 2 /*<<<*/) ? /* False branch >>>*/((1 < DivByX<0>::value2) ? 2 : 3)/*<<<*/ : 1 }; I did some template research and stumbled upon this annoying bug. It's really annoying because i need to do stuff like: template <int X> struct DivByX { enum { real_x = X == 0 ? 1 : X, value1 = X, value2 = int(100.f / value1) }; }; So the problem hides in the if-then-else branch, that is discarded because of the condition, but in fact processed by the compiler. Though this happens only when in the false branch expression there is template used. The error i get: test.cpp: In instantiation of ‘DivByX<0>’: test.cpp:63:89: instantiated from here test.cpp:52:5: warning: division by zero [-Wdiv-by-zero] test.cpp:52:5: error: ‘(1.0e+2f / 0.0f)’ is not a constant expression test.cpp:52:5: error: enumerator value for ‘value2’ is not an integer constant To give some comparison: clang works as intended. Thank you for your attention.
I think GCC is correct here as for a?b:c to be an integer constant expression, all three (a, b, and c) have to be an integer constant expressions even if a is true or false.
Hey Andrew. You words completely logical,. But I think it can be avoided when condition can be calculated during compilation. Though it's only my opinion. Though I still have a couple of counter arguments in my pocket :). First of all, clang++ compiles with out errors. Not an important argument, I know. The second one is code snippet: enum { valueA = 0, /// False branch in the condition should never be taken into account. /// And moreover, template should be constructed. valueB = (/* Always false >>>*/1 > 2 /*<<<*/) ? /* False branch >>>*/int(1.0f / 0)/*<<<*/ : 1 }; It doesn't whine about division by 0. So either former case or the later is a bug.
(Your testcase would be a lot easier to read without all those comments inside the conditional expression, I think it's safe to assume everyone here knows which is the false branch of a conditional expression!) A conditional expression is not a "static if" so templates in both branches of the conditional expression are instantiated, and instantiating DivByX<0> fails. You could work around this by preventing instantiation of the problem case, the simplest way is to specialize the template: template <> struct DivByX<0> { enum { value1 = X, value2 = 0; }; }; Now it doesn't matter if the DivByX<0> case is instantiated because it doesn't divide by zero.
Always nice to read friendly replies :). Sure I could. As I said, I'm not sure I was right in the first place. Just wanted to help to make gcc better than clang. Where I need no workarounds. Also, what about second case from my previous comment: enum { valueA = 0, valueB = (/1 > 2) ? int(1.0f / 0) : 1 }; Why doesn't this generate error, or at least warning? Thanks.
because it doesn't instantiate a template that requires the divide-by-zero in an integer constant context
Closing.