1

ALL,

I'm working on the project which involves heavy usage of STL and its cross-platform. On Windows I'm using MSVC 2010 Pro and on the Mac side I have XCode 4.2 on top of Snow Leopard.

My code looks like this:

m_sort.m_type.size() == 0 ? m_sort.m_type.push_back( SortObject( SORT_BY_NAME, true ) ) : m_sort.m_type.insert( it - 1, SortObject( SORT_BY_NAME, true ) );

where m_sort.m_type is std::vector<> which will be used for sorting another std::vector<>.

Visual Studio compiles this code fine: no warnings, no errors. However, trying to compile this code on XCode I'm getting this error:

Left operand to ? is void, but right operand is of type 'iterator' (aka '__normal_iterator')

Is there an easy way to resolve an error on Mac? And why this code was built successfully on Windows? Or maybe its a difference in STL implementation on XCode for SL vs MSVC on Windows?

Thank you.

Igor
  • 5,620
  • 11
  • 51
  • 103
  • 2
    The easiest way to fix this would probably be an explicit if branch. (I am assuming that the point of the ternary operator is to evaluate with side-efect one of the expressions, but not the other, which is not the correct way to use it.) – Xarn Feb 07 '14 at 00:02
  • In case this *happens* to be relevant - it's possibly the fact that XCode by default does not use the `libc++` standard library implementation - I know you're not using Boost, but in case this helps have a look at http://stackoverflow.com/a/20615086/368896 – Dan Nissenbaum Feb 07 '14 at 00:04
  • @Xarn, am I going to be hit performance wise? Also "?" saves source code lines. ;-) – Igor Feb 07 '14 at 00:07
  • @DanNissenbaum, interesting. Is there a proof somewhere? And yes I don't use Boost - I don't need an extra dependency. – Igor Feb 07 '14 at 00:09
  • If you care about performance you should be in a position to measure it. I doubt it will make a difference. In any case, your code is illegal so you have to fix it. – juanchopanza Feb 07 '14 at 00:10
  • @Igor - I could find proof, but how important is it that I find it for you? It's the way it is; I've had to deal with this and, in fact, I've had to explicitly set Xcode to use the `libc++` implementation. I doubt it matters in your case, since you can just use an `if` statement, but if you really want to unravel this, I do suggest that `libc++` might not to have this problem - though that assumes it is a result of the choice of standard library implementation - it might not be. – Dan Nissenbaum Feb 07 '14 at 00:14
  • Proof can probably be found by following the links in the link I provided. I trusted a comment by someone, and in fact trusting that comment solved the problem, so that was proof enough for me. – Dan Nissenbaum Feb 07 '14 at 00:16
  • @DanNissenbaum, About the proof - that was a rhetorical question. I was more talking to myself. But I will probably go with Xarn's suggestion as changing the project settings will require too much stuff to recompile. Thank you. – Igor Feb 07 '14 at 00:19
  • @DanNissenbaum, thank you for the link. Learn something new every day. ;-) – Igor Feb 07 '14 at 00:24
  • @Xarn, I upvoted you comment, but unfortunately there is no accept button. – Igor Feb 07 '14 at 02:47
  • @Igor Comments aren't supposed to be accepted, they are remarks and/or requests for clarification. Check Vlad's answer below whether it works (it should) and accept it. (Although I still think that using ternary to evaluate a side effect-only expression is ugly.) – Xarn Feb 07 '14 at 10:11
  • @Xarn, I changed the code to use if()/else and everything compiles. About the Vlad's comment - I don't feel comfortable casting the iterator to become "void". About the ternary operator - I was thjinking that since it will be used in sorting algorithm it will be better (faster). Also, some people push their comments as answers to increase the reputation on the site and let people know that they are good. ;-) – Igor Feb 08 '14 at 10:43
  • @Igor What the cast does is to show that the returned value (iterator) will be completely ignored. Anyway, I'll write up an answer together with some notes about performance of if/else vs ternary operator so you can pick whichever. – Xarn Feb 08 '14 at 14:53

2 Answers2

2

Write the following way

m_sort.m_type.size() == 0 ? 
   m_sort.m_type.push_back( SortObject( SORT_BY_NAME, true ) ) : 
   ( void )m_sort.m_type.insert( it - 1, SortObject( SORT_BY_NAME, true ) );

From the C++ Standard

2 If either the second or the third operand has type void, one of the following shall hold: — The second or the third operand (but not both) is a (possibly parenthesized) throw-expression (15.1); the result is of the type and value category of the other.

— Both the second and the third operands have type void; the result is of type void and is a prvalue. [ Note: This includes the case where both operands are throw-expressions. —end note ]

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

So, as already posted by Vlad, the problem is that the ternary expression cannot have combination of types ? void : T, unless the void-typed expression is a throw expression.

This can be solved either by

1) casting the return type of second operand to void, which basically means, that we only care about the side effects occurring and we are not actually returning from the expression

or

2) Transforming given ternary expression into an if/else branch.


Personally I strongly prefer option number 2, because it reduces the cognitive load on person reading it (and allows more space for explaining comment), and has no performance penalty.

Note, there are couple of cases in which using if/else statement does have a performance penalty over ternary operator, but only on low optimization settings, where compilers for a code looking like this:

if (is_ham){
    taste = 1;
} else {
    taste = 0;
}

emit branching execution path, instead of conditional move. However, on higher optimization settings (O2, O3), this code should emit the same instructions as this would.

taste = (is_ham)? 1 : 0;

Also note that for expressions with side effects, there has to be a branching execution path either way and that the expression in question is side effects only.

Xarn
  • 3,460
  • 1
  • 21
  • 43