指向独立函数和友元函数的指针之间的区别
Difference between a pointer to a standalone and a friend function
我不明白为什么以下代码无法编译(例如在 gcc 9.10 或 MS VS C++ 2019 中):
class X {
public:
friend bool operator==(int, X const &);
};
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
return 0;
}
但是下面的代码编译没有任何问题:
class X {
public:
};
bool operator==(int, X const &);
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // OK!
return 0;
}
我的期望是 X 的友元函数 (operator==) 表现为独立函数 (operator==)。我缺少什么?谢谢
不同之处在于,在第一个片段中,您只在 X
范围内声明运算符,而不是在外部。 main
无法访问 operator==(int,X const &)
。如果您修复它并在外部声明它,您只会收到警告:
class X {
public:
friend bool operator==(int, X const &);
};
bool operator==(int,X const&); // <--
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
return 0;
}
但是请注意,对于这两种情况,您都需要一个定义来实际调用运算符。
为了便于说明,请考虑
struct foo {
friend void bar() {
std::cout << "this is a inline definition of friend funtion";
}
};
从 foo
外部访问 bar
的唯一方法是在 foo
外部添加声明:
void bar();
What I'm missing?
内联友元声明不会使该函数可用于普通名称查找。
密切注意错误。它并没有说函数类型错误,它只是找不到任何名为 operator==
的东西。这是设计使然。
内联好友定义只能由 argument dependent lookup 找到。普通的查找(比如命名函数取其地址),是找不到的。如果您希望函数可用于该目的,则必须提供命名空间范围内的声明。
class X {
public:
friend bool operator==(int, X const &) { /* ... */ }
};
bool operator==(int, X const &);
Such a function is implicitly an inline ([dcl.inline]) function if it is attached to the global module. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not ([basic.lookup.unqual]).
来自标准namespace.memdef/3:
(感谢@StoryTeller)
If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]). [ Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship). — end note ] If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments ([basic.lookup.argdep]). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
以下不起作用,因为该函数在当前范围内不可见。
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
我不明白为什么以下代码无法编译(例如在 gcc 9.10 或 MS VS C++ 2019 中):
class X {
public:
friend bool operator==(int, X const &);
};
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
return 0;
}
但是下面的代码编译没有任何问题:
class X {
public:
};
bool operator==(int, X const &);
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // OK!
return 0;
}
我的期望是 X 的友元函数 (operator==) 表现为独立函数 (operator==)。我缺少什么?谢谢
不同之处在于,在第一个片段中,您只在 X
范围内声明运算符,而不是在外部。 main
无法访问 operator==(int,X const &)
。如果您修复它并在外部声明它,您只会收到警告:
class X {
public:
friend bool operator==(int, X const &);
};
bool operator==(int,X const&); // <--
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
return 0;
}
但是请注意,对于这两种情况,您都需要一个定义来实际调用运算符。
为了便于说明,请考虑
struct foo {
friend void bar() {
std::cout << "this is a inline definition of friend funtion";
}
};
从 foo
外部访问 bar
的唯一方法是在 foo
外部添加声明:
void bar();
What I'm missing?
内联友元声明不会使该函数可用于普通名称查找。
密切注意错误。它并没有说函数类型错误,它只是找不到任何名为 operator==
的东西。这是设计使然。
内联好友定义只能由 argument dependent lookup 找到。普通的查找(比如命名函数取其地址),是找不到的。如果您希望函数可用于该目的,则必须提供命名空间范围内的声明。
class X {
public:
friend bool operator==(int, X const &) { /* ... */ }
};
bool operator==(int, X const &);
Such a function is implicitly an inline ([dcl.inline]) function if it is attached to the global module. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not ([basic.lookup.unqual]).
来自标准namespace.memdef/3: (感谢@StoryTeller)
If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup ([basic.lookup.unqual]) or qualified lookup ([basic.lookup.qual]). [ Note: The name of the friend will be visible in its namespace if a matching declaration is provided at namespace scope (either before or after the class definition granting friendship). — end note ] If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments ([basic.lookup.argdep]). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
以下不起作用,因为该函数在当前范围内不可见。
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined