Consider the following code:
struct S {
using T = int;
operator T() { return 42; }
};
int main() {
S s;
S::T t = s;
// Is the following line correct?
t = s.operator T();
}
It compiles with GCC (4.9/5.1/6.1), but it fails to compile with clang (3.8/3.7).
The error returned is:
error: unknown type name 'T'; did you mean 'S::T'?
Which compiler is right in this case and why?
Note
Solving it is a matter of qualifying T
:
t = s.operator S::T();
The question is not about how to make it work.
Clang is much faster and uses far less memory than GCC. Clang aims to provide extremely clear and concise diagnostics (error and warning messages), and includes support for expressive diagnostics. GCC's warnings are sometimes acceptable, but are often confusing and it does not support expressive diagnostics.
Yes, for C code Clang and GCC are compatible (they both use the GNU Toolchain for linking, in fact.) You just have to make sure that you tell clang to create compiled objects and not intermediate bitcode objects.
But the framework underlying Clang called LLVM is extensible enough to support newer languages like Julia and Swift. From the perspective of C++, both are excellent compilers supporting the C++17 standard. From Incredibuild perspective, both are great tools. That's why we support both Clang and GCC.
GCC supports more language extensions and more assembly language features than Clang and LLVM. GCC is still the only option for compiling the Linux kernel.
I believe this is clang bug (submitted as #27807)
From [basic.lookup.classref]:
If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression. In each of these lookups, only names that denote types or templates whose specializations are types are considered. [ Example:
struct A { }; namespace N { struct A { void g() { } template <class T> operator T(); }; } int main() { N::A a; a.operator A(); // calls N::A::operator N::A }
—end example ]
In t = s.operator T();
, T
is first looked up in the class of S
, which should find your typedef and hence end up calling operator int()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With