namespace std
和 C 函数之间没有关系。但是您的代码不是 C,而是 C++,因此您还必须考虑 C++ 函数。例如std::tolower
,在 中<locale>
。你的问题是由于事情的一致:
您包含的标题之一包括<locale>
. C++ 头文件允许包含其他 C++ 头文件,并且哪个头文件包含哪个其他头文件可能因一种实现而异,因此您编写的代码可能使用一种编译器编译,而不是另一种编译器。
您试图将函数作为指向函数参数的指针传递给参数是模板类型参数的函数模板。简单来说,这里为了做重载解析
tolower
,编译器必须将其与参数的类型相匹配,而为了知道参数的类型,编译器必须根据函数的确切类型进行模板类型推导,它只有在完成重载解析后才能知道。
如果你想要这个函数<ctype.h>
(你不想要,因为它会导致未定义的行为),你可以通过 include
<ctype.h>
(保证它存在于全局命名空间中)和 using::tolower
或通过显式指定重载来获得它你想要,例如static_cast<int (*)(int)>( tolower )
(在这种特殊情况下,static_cast
并不意味着类型转换,而是显式重载决议。)
在实践中,当然,你不会做这种事情。如果您要进行任何文本处理,您会将所有必要的函数定义为函数对象类型,通过将输入转换为unsigned char
:
struct ToLower
{
char operator()( char ch ) const
{
return ::tolower( static_cast<unsigned char>( ch ) );
}
};
或通过使用<locale>
do使用的函数char
:
class ToLower
{
std::locale myLocale; // necessary to guarantee the lifetime of the facet.
std::ctype const* myCType;
public:
ToLower( std::locale const& loc = std::locale() )
; myLocal( loc )
, myCType( &std::use_facet<std::ctype>( loc ) )
{
}
bool operator()( char ch ) const
{
return myCType->tolower( ch );
}
};
最后,写下您的第二个问题:差异取决于您使用的 C++ 版本和编译器。然而,全局:<ctype.h>
将函数引入全局命名空间;<cctype>
会将它们引入命名空间std::
,并且可能(或可能不)引入全局命名空间。(并且您的第三个问题已经在上面得到了回答:std::tolower
指的是在<locale>
和中定义的一组重载函数<cctype>
;::tolower
指的是在中定义的单个函数<ctype.h>
,并且只是tolower
等价于
::tolower
,除非您已经完成using namespace std
,在这种情况下,它将指到上面提到的所有函数的重载集。