Igor
Igor

Reputation: 6267

Different compilation results: Mac vs Windows

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.

Upvotes: 1

Views: 1184

Answers (2)

Xarn
Xarn

Reputation: 3560

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.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311048

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 ]

Upvotes: 2

Related Questions