-
Notifications
You must be signed in to change notification settings - Fork 265
Description
Is 3 << 5 - 1 parsed as (3 << 5) - 1 or 3 << (5 - 1)? C++ and Go give different answers!
#include <iostream>
int main() { // Prints 48, which is "3 << (5 - 1)".
int x = 3 << 5 - 1;
std::cout << x << std::endl;
return 0;
}package main
import "fmt"
func main() { // Prints 95, which is "(3 << 5) - 1".
x := 3 << 5 - 1
fmt.Println(x)
}Similarly, 6 & 2 == 2 is 6 & (2 == 2) in C++ but (6 & 2) == 2 in Go. These reduce to 6 & 1 for C++ and 2 == 2 for Go, which are obviously different (0 and true).
For reference: C++ Operator Precedence and Go Operator Precedence
Like any curly-bracket language, Go looks a lot like C++, but copy/pasting a Go snippet from stackoverflow.com into a C++ program might have subtly different semantics.
I acknowledge that the SUGGESTION template says:
Please do not suggest syntax changes. I accept there are hundreds of opinions and everyone will prefer something a little different.
However, it also says "Please limit suggestions to quantifiable improvements to C++ simplicity, safety, or toolability" and there is a safety angle here. Operator precedence ambiguity has been a source of bugs in parsers. For example, in a library that emphasizes safety: jbangert/nail#7
Simplifying (by eliminating the idea of and need for precedence) is also similar to simplifying C++'s const T* type syntax. In C++, is it (const T)* or const (T*)? In cppfront, * const T is unambiguous, reading left-to-right.
The concrete suggestion: mandate parentheses when combining multiple binary operators. The programmer has to explicitly write either (3 << 5) - 1 or 3 << (5 - 1). A bare 3 << 5 - 1 would be a compiler error.