I'm porting WebGL GLSL shaders to OpenGL GLSL desktop using #version 120.
Is there any extension that would add support for the ?: ternary operator?
like:
#extension GL_EXT_***: enable
No extension needed, it's right in the base specification:
OpenGL Shading Language 1.20 Specification, section 5.9 "Expressions", page 38, 6th bullet:
The ternary selection operator (?:). It operates on three expressions (exp1 ? exp2 : exp3). This operator evaluates the first expression, which must result in a scalar Boolean. If the result is true, it selects to evaluate the second expression, otherwise it selects to evaluate the third expression. Only one of the second and third expressions is evaluated. The second and third expressions can be any type, as long their types match, or there is a conversion in Section 4.1.10 “Implicit Conversions” that can be applied to one of the expressions to make their types match. This resulting matching type is the type of the entire expression.
Related
I'm refreshing my memory about operator precedence, because I try to be smart guy and avoid parentheses as much as possible, refreshing on following 2 links:
cpp reference
MS docs
One problem I have, is that those 2 "reliable" docs are not telling the same thing, I no longer know whom to trust?
For one example, Cppreference says throw keyword is in same group as the conditional operator. Microsoft's docs say the conditional operator is higher than throw. There are other differences.
Which site is correct, or are both sites wrong in different ways?
TL;DR: The Microsoft docs can be interpreted to be less correct, depending on how you look at them.
The first thing you have to understand is that C++ as a language does not have "operator precedence" rules. C++ has a grammar; it is the grammar that defines what a particular piece of C++ syntax means. It is the C++ grammar that tells you that 5 + 3 * 4 should be considered equivalent to 5 + (3 * 4) rather than (5 + 3) * 4.
Therefore, any "operator precedence" rules that you see are merely a textual, human-readable explanation of the C++ grammar around expression parsing. As such, one can imagine that two different ways of describing the behavior of the same grammar could exist.
Consider the specific example of throw vs. the ?: operator. The Microsoft site says that ?: has higher precedence than throw, while the Cppreference site says that they have the same precedence.
First, let's look at a hypothetical C++ expression:
throw val ? one : two
By Microsoft's rules, the ?: operator has higher precedence, so would be parsed as throw (val ? one : two). By Cppreference's rules, the two operators have equal precedence. However, since they have right-to-left associativity, the ?: gets first dibs on the sub-expressions. So we have throw (val ? one : two).
So both of them resolve to the same result.
But what does the C++ grammar say? Well, here's a relevant fragment of the grammar:
throw-expression:
throw assignment-expression(opt)
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expression
This is parsed as a throw-expression, which contains an assignment-expression, which contains a conditional-expression, which is where our ?: lies. In short, the parser parses it as throw (val ? one : two).
So both pages are the same, and both of them are correct.
Now consider:
val ? throw one : two
How does this get parsed? Well, the thing to remember is that ?: is a ternary operator; unlike most others, it has three terms. That is, the conditional-expression itself is not finished being specified until the : <something> gets parsed.
So the precedence of throw vs ?: is irrelevant in this case. The throw one is within the ternary operator because the expression is literally within the ternary operator. The two operators are not competing.
Lastly, how about:
val ? one : throw two
Microsoft gives ?: higher precedence. By Microsoft's documentation, precedence "specifies the order of operations in expressions that contain more than one operator". So the ?: happens first.
Here's the rub though. throw by itself is actually a grammatically legal expression (it's only valid C++ within a catch clause, but the grammar is legal everywhere). As such, val ? one : throw could be a legitimate expression, which is what the Microsoft docs' rules would appear to say.
Of course, (val ? one : throw) two is not a legitimate expression, because () two isn't legal C++ grammar. So one could interpret Microsoft's rules to say that this should be a compile error.
But it's not. C++'s grammar states:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
throw two is the full assignment-expression used as the third operand of the given expression. So this should be parsed as val ? one : (throw two).
And what of Cppreference? Well, by giving them right-to-left associativity, the throw two is grouped with itself. So it should be considered val ? one : (throw two).
According to 5/1 (the Standard):
An expression can result in a value and can cause side effects.
So obviously we have two possible options:
1) Expression results in a value and cause side effects
2) Expression results in a value and doesn't cause side effects
What are the other possible options? (For example are there any expressions which don't result in a value?)
I thought about throw-expressions and functions with void return type. Can we refer them to the first or second category (value of void type with possible side effects)?
What are the other possible options?
Expression doesn't result in a value and causes side effects
Expression doesn't result in a value and does not cause side effects
Expressions with void return type do not result in a value. Expressions in 4. do not affect the behaviour of the program.
Given that exit(0) is an expression, we must include the possibility that evaluating an expression ends the program.
There are lots of questions on concepts of precedence and order of evaluation but I failed to find one that refers to my special case.
Consider the following statement:
if(f(0) && g(0)) {};
Is it guaranteed that f(0) will be evaluated first? Notice that the operator is &&.
My confusion stems from what I've read in "The C++ Programming Language, (Stroustrup, 4ed, 2013)".
In section 10.3.2 of the book, it says:
The order of evaluation of subexpressions within an expression is undefined. In particular, you cannot assume that the expression is evaluated left-to-right. For example:
int x = f(2)+g(3); // undefined whether f() or g() is called first
This seems to apply to all operators including && operator, but in a following paragraph it says:
The operators , (comma), && (logical and), and || (logical or) guarantee that their left-hand operand is evaluated before their right-hand operand.
There is also another mention of this in section 11.1.1:
The && and || operators evaluate their second argument only if necessary, so they can be used to control evaluation order (§10.3.2). For example:
while (p && !whitespace(p)) ++p;
Here, p is not dereferenced if it is the nullptr.
This last quote implies that && and || evaluate their 1st argument first, so it seems to reinforce my assumption that operators mentioned in 2nd quote are exceptions to 1st quote, but I cannot draw a definitive conclusion from this last example either, as the expression contains only one subexpression as opposed to my example, which contains two.
The special sequencing behavior of &&, ||, and , is well-established in C and C++. The first sentence you quoted should say "The order of evaluation of subexpressions within an expression is generally unspecified" or "With a few specific exceptions, the order of evaluation of subexpressions within an expression is unspecified".
You asked about C++, but this question in the C FAQ list is pertinent.
Addendum: I just realized that "unspecified" is a better word in these rules than "undefined". Writing something like f() + g() doesn't give you undefined behavior. You just have no way of knowing whether f or g might be called first.
Yes, it is guaranteed that f(0) will be completely evaluated first.
This is to support behaviour known as short-circuiting, by which we don't need to call the second function at all if the first returns false.
I'm studying the C++ programming language using Programming priciples and practice using C++.
I'm in chapter 4 now and in this chapter the book introduces the concept of expression, but I can't understand it at all :
The most basic building block in a program is an expression. An espression compute a value from a number of operands. The simplest expression in C++ is simply a literal value such as 11, 'c', "hello". Names of variables are also expressions. A variable represent the object which it is the name.
Why a literal is considered an expression ? Why the name of a variable is considered an expression ?
Expressions -in programming languages, in math, in linguistics- are defined compositionally (or inductively). So expressions are often made of subexpressions like x*2+y*4 is made of two sub-expressions x*2 and y*4 joined by the addition operator +.
But you need a base case (the most atomic and simple expressions). These are literals (2) and variables (x) - if either of them was not an expression 2*x could not be an expression (since both operands of the binary multiplication * are sub-expressions).
Notice that in C and C++ assignments and function calls are expressions
Think of it like this: An expression is a sequence of steps that produce a value. Thus, 4+3 is a two-step expression, because you (1) start with the number 4, and (2) add 3 to it.
Therefore, 7 can be regarded as a single-step sequence, because there is only one "action" performed: (1) start with the number 7.
Thus, both a = 4+3; and a = 7; can be generalised to a = <expression>;.
An expression is "a sequence of operators and operands that specifies a computation" (http://en.cppreference.com/w/cpp/language/expressions).
Let see a simple expression: 3 + 3. When you evaluate this expression, you will get the result 6.
So let see another expression: 3. When you evaluate this expression, you will get the result 3.
A literal is considered an expression because a literal is a type of constant and constants are expressions with a fixed value.
A variable is also considered as an expression because it can be used as an operand within another expression or as an expression by itself.
In software design, composite pattern can be used as a representation of the expression.
I was just going though my text book when I came across this question:
What would be the value of a after the following expression? Assume the initial value of a = 5. Mention the steps.
a+=(a++)+(++a)
At first I thought this is undefined behaviour because a has been modified more than once. Then I read the question and it said "Mention the steps" so I probably thought this question is right.
Does applying parentheses make an undefined behaviour defined?
Is a sequence point created after evaluating a parentheses expression?
If it is defined,how do the parentheses matter since ++ and () have the same precedence?
No, applying parentheses doesn't make it a defined behaviour. It's still undefined. The C99 standard §6.5 ¶2 says
Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be read only to determine the value
to be stored.
Putting a sub-expression in parentheses may force the order of evaluation of sub-expressions but it does not create a sequence point. Therefore, it does not guarantee when the side effects of the sub-expressions, if they produce any, will take place. Quoting the C99 standard again §5.1.2.3¶2
Evaluation of an expression may produce side effects. At certain
specified points in the execution sequence called sequence points, all
side effects of previous evaluations shall be complete and no side
effects of subsequent evaluations shall have taken place.
For the sake of completeness, following are sequence points laid down by the C99 standard in Annex C.
The call to a function, after the arguments have been evaluated.
The end of the first operand of the following operators: logical AND &&; logical OR ||; conditional ?; comma ,.
The end of a full declarator.
The end of a full expression; the expression in an expression statement; the controlling expression of a selection statement (if
or switch); the controlling expression of a while or do
statement; each of the expressions of a for statement; the
expression in a return statement.
Immediately before a library function returns.
After the actions associated with each formatted input/output function conversion specifier.
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any
movement of the objects passed as arguments to that call.
Adding parenthesis does not create a sequence point and in the more modern standards it does not create a sequenced before relationship with respect to side effects which is the problem with the expression that you have unless noted the rest of this will be with respect to C++11. Parenthesis are a primary expression covered in section 5.1 Primary expressions, which has the following grammar (emphasis mine going forward):
primary-expression:
literal
this
( expression )
[...]
and in paragraph 6 it says:
A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression. The presence of parentheses does not affect whether the expression is an lvalue. The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated.
The postfix ++ is problematic since we can not determine when the side effect of updating a will happen pre C++11 and in C this applies to both the postfix ++ and prefix ++ operations. With respect to how undefined behavior changed for prefix ++ in C++11 see Assignment operator sequencing in C11 expressions.
The += operation is problematic since:
[...]E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is
evaluated only once[...]
So in C++11 the following went from undefined to defined:
a = ++a + 1 ;
but this remains undefined:
a = a++ + 1 ;
and both of the above are undefined pre C++11 and in both C99 and C11.
From the draft C++11 standard section 1.9 Program execution paragraph 15 says:
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. —end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.