Is this response from the compiler valid?
Add a space after the =
. (=[
looks too sad to be an operator.) It's probably seeing =value
as a use of a (possible, but not implemented) prefix operator.
Swift isn't entirely whitespace-agnostic like C... in particular, it uses whitespace to distinguish prefix from postfix operators (because ++i++
in C is a grammar oddity). But it's not ridiculously strict about whitespace like Python either.
Why does != 0 cause a compiler error
This is probably due to the lack of whitespace around your !=
operator - Swift is quite fussy about whitespace, and interprets operators differently depending on their surrounding whitespace.
The language specification describes the various rules, although it is not particularly obvious from these that b!=0
should be invalid.
So you probably need to say b != 0
rather than b!=0
See also: Is this response from the compiler valid?
Swift: '==' is not a prefix unary operator
Try to add space after '=='.
Instead of :
if(result =="") {
try:
if(result == "") {
Is Type(::x); valid?
As far as I can tell this is covered by draft C++ standard section 8.3
Meaning of declarators paragraph 6 which says (emphasis mine going forward):
In a declaration T D where D has the form
( D1 )
the type of the contained declarator-id is the same as that of the contained declarator-id in
the declarationT D1
Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex
declarators.
so:
int(::x);
is equivalent to:
int ::x ;
which is clearly not valid, and this produces the same error as well. So gcc 4.9
is not correct here but since this looks fixed in the gcc 4.8.3
which was released later I would expect this to be fixed in later releases of 4.9
as well. Although I don't see any obvious matches for this issue in the gcc 4.8.3 bugs fixed list but they don't claim it is a complete list.
The second case is a functional explicit type conversion which is covered in section 5.2.3
Explicit type conversion (functional notation) which says:
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6)
followed by a parenthesized expression-list constructs a value of the
specified type given the expression list. If the expression list is a
single expression, the type conversion expression is equivalent (in
definedness, and if defined in meaning) to the corresponding cast
expression (5.4).[...]
This is unambiguous since ::x + 2
is an expression.
The section that covers when a statement is considered a declaration or a expression is 6.8
Ambiguity resolution which says:
There is an ambiguity in the grammar involving expression-statements
and declarations: An expressionstatement with a function-style
explicit type conversion (5.2.3) as its leftmost subexpression can be
indistinguishable from a declaration where the first declarator starts
with a (. In those cases the statement is a declaration. [ Note: To
disambiguate, the whole statement might have to be examined to
determine if it is an expression-statement or a declaration. This
disambiguates many examples.
and provides the following examples:
T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5)<<c; // expression-statement
T(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration
Note: without the ()
then T ::D
is a qualified-id in the case of T
being a class, that is a covered in the grammar of 5.1
Primary expressions.
Update
Filed a gcc bug report.
gcc's response is that:
Current G++ and EDG both treat it as the valid expression (int)::x
Since this response implies clang
is incorrect(I don't agree though), I filed a clang bug report and older bug report looks similar and seems to disagree with the gcc
response.
Update 2
In response to the clang bug report
Richard Smith agrees this should be treated as a declaration and says:
That does not imply clang is incorrect; in fact, Clang is correct
here, as far as I can see. (I've also sent a bug report to EDG.)That said, we should give a proper 'you hit a vexing parse, here's how
to disambiguate' error in this case.
Update 3
gcc
confirms it is a bug.
Why std::is_functionT is causing compilation error?
The issue is here:
template <class InputIterator, class Function>
Function my_for_each(InputIterator first, InputIterator last, Function f)
invoked via:
my_for_each(vec_x.begin(), vec_x.end(), display);
This deduces Function
(of my_for_each
) to be a function pointer; for
void display(int& val)
the deduced type is void(*)(int&)
. The type trait std::is_function
however checks if the passed type is a function type, not a function pointer type.
One solution is to remove the pointer:
template<typename T>
constexpr bool Is_valid_function(T& a) {
return std::is_function<typename std::remove_pointer<T>::type>::value;
}
But, as clang++ reveals, this still isn't sufficient:
template<typename T>
void check_valid_function(T& a) {
static_assert(Is_valid_function(a), "Not The Valid Function");
}
a
as a function parameter (even if check_valid_function
was constexpr
!) is not a compile-time constant, therefore it may not appear in a constant expression (inside the function body). Hence, Is_valid_function(a)
may not appear as the check for the static_assert
. It might be possible to use something similar to declval
, e.g.
static_assert(Is_valid_function( declval<T&>() ), "Not The Valid Function");
but unfortunately, declval
is not constexpr
, and I don't know how to write a constexpr
version. So, you could pass a pointer instead:
static_assert(Is_valid_function(static_cast<T*>(nullptr)),
"Not a valid function");
For this, you need to rewrite Is_valid_function
as follows:
template<typename T>
constexpr bool Is_valid_function(T*) {
return std::is_function<typename std::remove_pointer<T>::type>::value;
}
Note: the passed argument here is a pointer to a pointer to a function, but the parameter T*
deduced T
to be a pointer to a function, as before (hence the change in the signature). You might want to reflect that in the function name, if you choose this solution.
Other issues:
Relying on ADL for Standard Library algorithms
return for_each(first, last, f) ;
As far as I can see, this relies on ADL. But the iterators (and the function) are not required to be in namespace
std
(even forvector::iterator
etc.), so you shouldn't rely on ADL:return std::for_each(first, last, f);
Use of non-const refs for functions that don't need to modify their arguments, e.g.
constexpr bool Is_valid_function(T& a)
If you don't need to modify an argument, you should either pass it by value or by const reference, e.g.
constexpr bool Is_valid_function(T const& a)
"Wrong check" If this code is just for educational purposes, this isn't an issue. However, the check if the passed argument is of a function type is the "wrong check" when trying to check if the argument valid for a Standard Library algorithm. You should rather check whether
f(*first)
is well-formed. This allows for function objects and checks if the argument type is "valid".
Why is n+++n valid while n++++n is not?
The file is tokenized (transformed into sequence of tokens) first with the maximal munch rule - always get longest possible valid token. Your text is transformed to following sequence:
n ++ ++ n
And this is not valid expression.
From JLS §3.2:
3.2. Lexical Translations
A raw Unicode character stream is translated into a sequence of tokens, using the following three
lexical translation steps, which are applied in turn:
A translation of Unicode escapes (§3.3) in the raw stream of Unicode
characters to the corresponding Unicode character. A Unicode escape
of the form \uxxxx, where xxxx is a hexadecimal value, represents
the UTF-16 code unit whose encoding is xxxx. This translation step
allows any program to be expressed using only ASCII characters.A translation of the Unicode stream resulting from step 1 into a stream of input characters and line terminators (§3.4).
A translation of the stream of input characters and line terminators resulting from step 2 into a sequence of input elements
(§3.5) which, after white space (§3.6) and comments (§3.7) are
discarded, comprise the tokens (§3.5) that are the terminal symbols
of the syntactic grammar (§2.3).
The longest possible translation is used at each step, even if the result does not ultimately make a correct program while another
lexical translation would.(Thus, the input characters
a--b
are tokenized (§3.5) asa, --, b
,
which is not part of any grammatically correct program, even though
the tokenizationa, -, -, b
could be part of a grammatically correct
program.)
unable to compile a code when converted into a function
i was able to solve it but now I am left with more questions than answers. Would appreciate if someone could explain the behaviour to me.
I was using the following httpOptions
object
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true,
observe: 'response' as 'response',
};
as was using it as follows in some places in the code.
return this.http.post(this.SIGNUP_USER_URL,body,httpOptions)
This worked.
Then I thought of changing the http.post
into a function sendMessage
(as explained in the question) and replaced it in only once place (remember I am using this.http.post
in several places so wanted to try it at one place to begin with). I noticed that using httpOptions
made post
return Observable<ArrayBuffer>
.
Doubt 1 - why?
Then I changed httpOptions
to
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true,
observe: 'response' as 'response',
responseType:'json'
};
It started giving me errors at places where I am using http.post
directly (without sendMessage
. The error was
ERROR in src/app/web-to-backend-interface.service.ts(81,71): error TS2345: Argument of type '{ headers: HttpHeaders; withCredentials: boolean; observe: "response"; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
Types of property 'observe' are incompatible.
Type '"response"' is not assignable to type '"body"'.
src/app/web-to-backend-interface.service.ts(112,52): error TS2345: Argument of type '{ headers: HttpHeaders; withCredentials: boolean; observe: "response"; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
Types of property 'observe' are incompatible.
Type '"response"' is not assignable to type '"body"'.
src/app/web-to-backend-interface.service.ts(196,73): error TS2345: Argument of type '{ headers: HttpHeaders; withCredentials: boolean; observe: "response"; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
src/app/web-to-backend-interface.service.ts(216,72): error TS2345: Argument of type '{ headers: HttpHeaders; withCredentials: boolean; observe: "response"; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
src/app/web-to-backend-interface.service.ts(251,54): error TS2345: Argument of type '{ headers: HttpHeaders; withCredentials: boolean; observe: "response"; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
src/app/web-to-backend-interface.service.ts(291,9): error TS2322: Type 'Observable<ArrayBuffer>' is not assignable to type 'Observable<HttpEvent<any>>'.
Type 'ArrayBuffer' is not assignable to type 'HttpEvent<any>'.
Type 'ArrayBuffer' is not assignable to type 'HttpUserEvent<any>'.
Property 'type' is missing in type 'ArrayBuffer'.
So I removed responseType:'json'
from httpOptions
and added an explicit object in this.http.post
in my sendMessage
which worked!
private sendMessage(url:string, body:any,httpOptions){
...
let observable:Observable<HttpEvent<any>> = this.http.post(url,body,{
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true,
observe: 'events',
responseType: 'json'
})
...
}
there seem to be relationship between observe and responseType. Eg observe=body and responseType=text means that post should observe (look in) the body, interpret it as text and return Observable. But I wonder why I just couldn't change httpOptions
Code is valid in Eclipse, cannot be compiled by the JDK
javac 1.7.0_04 compiles the source without error, so I'd suggest this is a bug in javac 1.6.
Related Topics
Why Optional Constant Does Not Automatically Have a Default Value of Nil
What Is the 'Open' Keyword in Swift
Non-'@Objc' Method Does Not Satisfy Optional Requirement of '@Objc' Protocol
Using a Type Variable in a Generic
Call a Method from a String in Swift
How to Generate a Random Number in a Range (10...20) Using Swift
Get Class Name of Object as String in Swift
How to Use Swift'S Codable to Encode into a Dictionary
Use Binding≪Int≫ With a Textfield Swiftui
Check If 'Any' Value Is Object
Swift Lazy Instantiating Using Self
Swift Optional Escaping Closure Parameter
Nsobject Subclass in Swift: Hash VS Hashvalue, Isequal VS ==
How to Convert a Base64String to String in Swift
Getting a "This Application Is Modifying the Autolayout Engine from a Background Thread" Error