Scope resolution operator for isalnum
我正在问这个问题,以作为对此问题的后续行动。上一个问题是在大约三年前提出的,所以尽管我提出一个新的问题会更好。
我链接到这个问题的症结在于,OP试图运行以下代码行:
1
| find_if(s.begin(), s.end(), isalnum); |
在某个容器s上。代码行无法编译,OP应该执行了此操作
1
| find_if(s.begin(), s.end(), ::isalnum); |
可接受的答案指出,在locale和cctype库中有isalnum函数,并且编译器在消除两者之间的歧义时遇到了麻烦,因此::范围解析运算符。我仅通过包含其中一个库进行了测试,而编译器仍然存在一些歧义。这是为什么?如果我仅包括这些库中的一个,那么显然编译器不应该"知道"另一个库,那么为什么会发生冲突呢?
问题的第二部分是::运算符如何告诉我们我们想要哪个isalnum函数?
谢谢
编辑
我知道::运算符告诉我们我们想要的函数/变量在全局范围内,但这仍然不能回答我的第二个问题。
<locale>中的isalnum在名称空间std中定义。 <cctype>中的isalnum是在名称空间std中定义的,并且是全局定义的,因为C库中的符号(可能是[1])在全局范围内可用。使用::isalnum要求从全局范围而不是namespace std要求isalnum的版本。
[1]。该标准保证,如果包含<ctype.h>,则符号将位于全局范围内。对于C库头文件,对于cc*版本,几乎也总是如此,尽管严格地来说,它是由实现定义的。
- 好的,因此即使我不包括<cctype>,C库中的符号在默认情况下仍可用?因为它编译时不包含这两个库中的任何一个。如果我仅包括其中之一,它仍然无法回答我的问题,为什么编译器仍然会发生名称冲突。
-
这些符号默认情况下不可用,但是实现可能包括其他标准头中的标准头。
-
@Andrew,"因为C库中的符号在全局范围内可用"。不必要。它们可能在全球范围内,但可能不在全球范围内。仅当包含<ctype.h>时才保证。
-
@JonathanWakely这是事实。病态修改答案以添加该警告。
-
@Andrew,所以您是说通过我包含的其他标头也同时包含了<locale>和<cctype>,因此是否存在冲突?
-
@KonradKapp是的。最有可能的。
-
@Andrew OK,谢谢。最后一个问题:要访问locale中的功能而不是cctype,我要写什么?我做了一些阅读,并建议将参数强制转换为与所需函数匹配的特定函数指针。那是唯一的方法吗?
-
不,您还可以使用lambda函数,以便对alnum进行调用的重载解析:find_if(s.begin(), s.end(), [](unsigned char c){ return std::isalnum(c); });
-
@JonathanWakely,所以我假设上面的lambda函数会调用cctype版本,因为它与cctype签名匹配?
-
@KonradKapp,是的。显然,如果要在<locale>中调用两个参数的版本,则可以使用两个参数(而不是一个)来调用它。
据我了解,使用范围解析运算符(::)有助于确定程序的范围。
因此,如果您有:
1 2 3 4 5 6
| Add(); //This is in Global Scope
class Test{
void Add(); //This is in scope of the"Test" class
int useAdd(); { ::Add();}
} |
因此在这种情况下,useAdd()函数是指全局范围内的add函数,而不是测试类中的add函数。如果要使用范围解析运算符引用测试类中的那个,则应放置Test::Add()而不是::Add()。
在上述情况下,可能是他在当前类以及全局函数中都实现了" isalnum"函数,并且他需要专门引用全局函数而不是类函数。 >
编辑:我想我误解了这个问题,安德鲁比我自己回答得更好。