cast 运算符函数在 g++ 中编译良好,但在其他编译器中则不然。为什么?
cast operator function compiles fine in g++ but not in other compilers. Why?
考虑以下程序:
struct S {
using T = float;
operator T() { return 9.9f; }
};
int main() {
S m;
S::T t = m;
t = m.operator T(); // Is this correct ?
}
该程序在 g++ 中编译良好(参见现场演示 here)
但在 clang++、MSVC++ 和 Intel C++ 编译器中编译失败
clang++ 给出以下错误(参见现场演示 here)
main.cpp:8:20: error: unknown type name 'T'; did you mean 'S::T'?
t = m.operator T(); // Is this correct ?
^
S::T
main.cpp:2:11: note: 'S::T' declared here
using T = float;
MSVC++ 给出以下错误(参见现场演示 here)
source_file.cpp(8): error C2833: 'operator T' is not a recognized operator or type
source_file.cpp(8): error C2059: syntax error: 'newline'
英特尔 C++ 编译器也拒绝此代码(参见现场演示 here)
所以,问题是哪个编译器就在这里? g++ 在这里不正确还是其他 3 个编译器在这里不正确? C++ 标准对此有何规定?
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]
这表明该示例可能没问题,尽管在上面的示例中,A
之前已声明为类型名称,对 main
可见。
这在 core issue 156 中进行了讨论,早在 1999 年就提交了:
How about:
struct A { typedef int T; operator T(); };
struct B : A { operator T(); } b;
void foo() {
b.A::operator T(); // 2) error T is not found in the context
// of the postfix-expression?
}
Is this interpretation correct? Or was the intent for this to be an
error only if T
was found in both scopes and referred to different
entities?
Erwin Unruh: The intent was that you look in both contexts. If you find it only once, that's the symbol. If you find it in both, both symbols must be "the same" in some respect. (If you don't find it, its an error).
所以我要说 Clang 是错误的:正如措辞在某种程度上表达的那样,我们找到 T
的意图,即使只在 class.
考虑以下程序:
struct S {
using T = float;
operator T() { return 9.9f; }
};
int main() {
S m;
S::T t = m;
t = m.operator T(); // Is this correct ?
}
该程序在 g++ 中编译良好(参见现场演示 here)
但在 clang++、MSVC++ 和 Intel C++ 编译器中编译失败
clang++ 给出以下错误(参见现场演示 here)
main.cpp:8:20: error: unknown type name 'T'; did you mean 'S::T'?
t = m.operator T(); // Is this correct ?
^
S::T
main.cpp:2:11: note: 'S::T' declared here
using T = float;
MSVC++ 给出以下错误(参见现场演示 here)
source_file.cpp(8): error C2833: 'operator T' is not a recognized operator or type
source_file.cpp(8): error C2059: syntax error: 'newline'
英特尔 C++ 编译器也拒绝此代码(参见现场演示 here)
所以,问题是哪个编译器就在这里? g++ 在这里不正确还是其他 3 个编译器在这里不正确? C++ 标准对此有何规定?
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]
这表明该示例可能没问题,尽管在上面的示例中,A
之前已声明为类型名称,对 main
可见。
这在 core issue 156 中进行了讨论,早在 1999 年就提交了:
How about:
struct A { typedef int T; operator T(); }; struct B : A { operator T(); } b; void foo() { b.A::operator T(); // 2) error T is not found in the context // of the postfix-expression? }
Is this interpretation correct? Or was the intent for this to be an error only if
T
was found in both scopes and referred to different entities?Erwin Unruh: The intent was that you look in both contexts. If you find it only once, that's the symbol. If you find it in both, both symbols must be "the same" in some respect. (If you don't find it, its an error).
所以我要说 Clang 是错误的:正如措辞在某种程度上表达的那样,我们找到 T
的意图,即使只在 class.