Visual C++ 2008 - Compliance?
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
It appears that both are compliant: "If no valid specialization can be generated for a template definition, and that template is not instantiated, it is unspecified whether or not an implementation is required to issue a diagnostic." (This is at 14.6.5. It is about name resolution, but arguably applies to other issues.)
Anyone who thinks he has a better idea of what's good for people than people do is a swine. - P.J. O'Rourke
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
Looks to me like an optimisation in the compiler. It does not resolve this template declaration until it it used, possibly missing the syntax error. Perhaps there is a compiler option to change this behavior.
A while ago he asked me what he should have printed on my business cards. I said 'Wizard'. I read books which nobody else understand. Then I do something which nobody understands. After that the computer does something which nobody understands. When asked, I say things about the results which nobody understand. But everybody expects miracles from me on a regular basis. Looks to me like the classical definition of a wizard.
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
John R. Shaw wrote:
template int test(T n) { return n }
I guess the missing semicolon after n is just a typo...
Best regards, Jaime.
-
It appears that both are compliant: "If no valid specialization can be generated for a template definition, and that template is not instantiated, it is unspecified whether or not an implementation is required to issue a diagnostic." (This is at 14.6.5. It is about name resolution, but arguably applies to other issues.)
Anyone who thinks he has a better idea of what's good for people than people do is a swine. - P.J. O'Rourke
-
Yes, this is legal behaviour. Andrei Alexandrescu wrote in his "Modern C++ Design" some cases where this can be very useful. Unfortunatly I don't have them in mind atm...
I have seen this kind of things being used in Metaprogramming to generate Sin/Cos tables.
1. I will develop myself to the maximum of my potential in all ways 2. I will look for the good in all people and make them feel worthwhile. 3. If I have nothing good to say about a person, I will say nothing. 4. I will always be as enthusiastic about the success of others as I am about my own. 5. I will always remain loyal to God, my country, family and my friends - Chuck Norris
Ernest Laurentin -
Yes, this is legal behaviour. Andrei Alexandrescu wrote in his "Modern C++ Design" some cases where this can be very useful. Unfortunatly I don't have them in mind atm...
I believe what you are referring to is the SFINAE (Substitution Failure Is Not An Error) paradigm, I don't believe it relates to this issue. As Joe pointed out section 14.6.5 defines what the standard expects as a minimum from a compliant compiler. This particular definition gives the compiler vendor leeway in choosing between faster compile times or more robust error reporting. As a solution the user may decide to explicitly specialize all templated function with reasonable/anticipated types for robust build purposes. eg:
template<typename T> inline T foo1(const T& v) { return v * T(1); } template<typename T> inline T foo2(const T& v) { return v * T(2); } template<typename T> inline T foo3(const T& v) { return v * T(3); } #define INSTANTIATE_FUNCTIONS(T)\ template inline T foo1<T>(const T& v);\ template inline T foo2<T>(const T& v);\ template inline T foo3<T>(const T& v); INSTANTIATE_FUNCTIONS(float) INSTANTIATE_FUNCTIONS(double) INSTANTIATE_FUNCTIONS(int)
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
What error are you referring? A) the compiler does not provide any error for the missing ";" unless you don't instatiate the function. I don't see this behavior in VC8 B) The compiler dosn't provide an error for return n where n is a T rather than an int. It's just SFINAE: until you don't know what T is you cannot assume T is not implicitly convertible into int. think to
class C { operator int() const { return _some_int_; } };
test(C())
will result in_some_int_
.2 bugs found. > recompile ... 65534 bugs found. :doh:
-
template<typename T> int test(T n) { return n }
Interesting! VC does not recognize this syntax error until someone tries to call it; at which point the error occurs during the generation of the function. The GCC compiler does not care if you call it or not, because it is still an error. The VC compiler does not care unless the function (or method) is called, as shown below.
template<typename T> int test(T n)
The above demonstrates one of the reasons why your test scripts must call every single version of your template functions (or methods). This appears to be a standards compliance problem; is it? :doh: If it is not; why not? My colleague (who found it) and I believe it should be.
INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
The root cause of the issue is that Visual C++ does not parse the contents of the template until it is instantiated. At that point it knows what T is (and any other template parameters) and can perform macro-like substitutions to compile. This behaviour is at odds with the standard, and it prevents non-dependent name lookup from working correctly. See here[^] for the documentation of this issue. Other compilers such as GCC have implemented this feature correctly, parsing the template fully at the point that it is encountered and binding the non-dependent names at that point. This makes the parser much more complicated, however. The problem is that C++ is highly ambiguous between declarations and expressions, and this is deliberate - declarations are intended to mirror their use. I once tried to implement a C++ parser. It was very, very hard. My view of the situation seven years ago can be found here[^]. At the time, I felt that C and C++ had such a bad syntax for tools that they shouldn't be used as a basis for any further languages. Now, I recognize that they're good languages for humans to write in, which may trump the difficulty of parsing.
DoEvents: Generating unexpected recursion since 1991
-
What error are you referring? A) the compiler does not provide any error for the missing ";" unless you don't instatiate the function. I don't see this behavior in VC8 B) The compiler dosn't provide an error for return n where n is a T rather than an int. It's just SFINAE: until you don't know what T is you cannot assume T is not implicitly convertible into int. think to
class C { operator int() const { return _some_int_; } };
test(C())
will result in_some_int_
.2 bugs found. > recompile ... 65534 bugs found. :doh:
The template function “test” was just an example; what was returned is not important here. Change it to “
return 1
” if you like.
VC8 did not catch the syntax error (missing “;”) until it was instantiated; the GCC compiler flagged it as a syntax error, even though it was not instantiated.
In other words: VC8 produced an executable without complaint and GCC would not, until the error was corrected.
I think that VC8 is technically correct, as the result of the compilation should not depend on code that was not instantiated, even if that code is invalid. On the other hand, GCC forces the developer to fix the error, whether instantiated or not, which is much more useful in the long run, as it reduces errors now instead of latter.INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
-
The template function “test” was just an example; what was returned is not important here. Change it to “
return 1
” if you like.
VC8 did not catch the syntax error (missing “;”) until it was instantiated; the GCC compiler flagged it as a syntax error, even though it was not instantiated.
In other words: VC8 produced an executable without complaint and GCC would not, until the error was corrected.
I think that VC8 is technically correct, as the result of the compilation should not depend on code that was not instantiated, even if that code is invalid. On the other hand, GCC forces the developer to fix the error, whether instantiated or not, which is much more useful in the long run, as it reduces errors now instead of latter.INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
Thanks: now I've got the point.
2 bugs found. > recompile ... 65534 bugs found. :doh: