没有函数模板实例remove_if与参数列表匹配
No instance of function template remove_if matches argument list
我正在尝试从字符串中删除空格
line.erase(remove_if(line.begin(), line.end(), isspace), line.end());
但是Visual Studio 2010(C++ Express)告诉我。
1 IntelliSense: no instance of function template "std::remove_if" matches the argument list d:parsertryparsertrycalc.cpp 18
完整来源
为什么?一段简单的代码
int main() {
string line = "hello world 111 222";
line.erase(remove_if(line.begin(), line.end(), isspace), line.end());
cout << line << endl;
getchar();
return 0;
}
验证函数是否有效?
有趣的是,尽管如此,它还是运行给出了正确的结果。
不要质疑智能感知,有时最好忽略它。解析器或数据库以某种方式搞砸了,因此它不再正常工作。通常,重新启动将解决问题。
如果你真的想知道代码是否格式不正确,那么,只需按 F7 进行编译。
使用 VisualC++ 11.0(Visual Studio 2012 附带的编译器)进行编译时,源代码甚至没有警告。
智能感知使用自己的规则,并不总是可靠的。
也就是说,您对除原始 7 位 ASCII 之外的所有字符集使用isspace
是未定义的行为。这意味着你从中得到的大量赞成的答案只是秃头(这不应该令人惊讶)。您需要将参数强制转换为(C 库的)isspace
unsigned char
以避免负值和 UB。
C99 §7.4/1(来自 N869 草案):
标头
<ctype.h>
声明了几个对测试和映射有用的函数 字符。 在所有情况下,参数都是一个int
,其值应为 可表示为unsigned char
或应等于宏EOF
的值。如果 参数具有任何其他值,行为未定义。
包装 C 函数的一种简单方法是
bool isSpace( char const c )
{
typedef unsigned char UChar;
return !!::isspace( UChar( c ) );
}
为什么typedef
?
它使代码更容易适应以下情况 你已经有这样的
typedef
,这并不少见;它使代码更清晰;和
它避免了 C 语法强制转换,从而避免了通过正则表达式或其他模式匹配进行搜索时的误报。
但是,为什么!!
(否定运算符的双重应用)?考虑到从int
到bool
的自动隐式转换?而且,如果一个人绝对觉得转换应该是明确的,那么它不应该是一个static_cast
,而不是!!
吗?
好吧,!!
避免了来自Visual C++编译器的愚蠢警告,
C4800:"int":强制值为布尔值"真"或"假"(性能警告)">
static_cast
并不能阻止这种警告。消除该警告是一种很好的做法,并且由于Visual C++是最常用的系统(即Windows)上的主要C++编译器,因此最好在所有可移植的代码中执行此操作。
哦,好吧,但是,既然无论如何都必须包装函数,那么......当<locale>
标头提供更灵活的C++(两个参数)isspace
函数时,为什么要使用旧的 C 库isspace
(单参数)函数?
嗯,首先,旧的 Cisspace
函数是问题中使用的函数,所以这就是这个答案中讨论的函数。我专注于讨论如何不错误地执行此操作,即如何避免未定义的行为。讨论如何正确地做到这一点会把它带到一个完全不同的水平。
但是在实践中,同名的C++级函数可以被认为是被破坏的,因为直到最近才使用g ++编译器(甚至可能使用g ++ 4.7.2,我最近还没有检查)只有C语言环境机制有效,而C++级机制在Windows中不起作用。它可能已经修复,因为 g++ 现在支持宽流,我不知道。无论如何,C库isspace
功能,除了在实践中更便携并且通常在Windows中工作之外,也更简单,我相信更有效率(尽管为了提高效率,如果它被认为是重要的,应该始终测量!
感谢James Kanze在评论中提出(基本上)上述问题。
什么是isspace
? 取决于包含标头和编译器 您正在使用,您的代码甚至可能无法编译。 (我不 了解智能感知,但它可能正在查看所有 标准标头,并看到歧义。
标准中有两个isspace
功能,一个是 模板。 将函数模板传递给另一个函数的模板参数 函数模板没有为编译器提供足够的信息 为了能够进行模板参数推导:为了解决isspace
的重载,它必须知道预期的类型remove_if
,它只有在模板参数推导后才知道 成功。 并且要对remove_if
进行模板参数推导,它具有 要知道参数的类型,这意味着isspace
的类型, 只有当它能够解决过载问题时,它才会知道 它。
(我真的很惊讶你的一点代码编译:你 显然包括<iostream>
,通常,<iostream>
将包括<locale>
,这将引入函数模板isspace
。
当然,函数模板isspace
必须用两个调用 参数,所以如果它被选中,remove_if
的实例化 不会编译(但编译器不会尝试实例化remove_if
直到它选择了函数)。 而isspace
如果传递char
,<ctype.h>
将导致未定义的行为,因此您 不能使用它。 通常的解决方案是创建一组谓词 工具箱中的对象,然后使用它们。 如下所示 如果您只关心char
,应该可以工作:
template <std::ctype<char>::mask m>
class Is : public std::unary_function<char, bool>
{
std::locale myLocale; // To ensure lifetime of following...
std::ctype<char> const* myCType;
public:
Is( std::locale const& loc = std::locale() )
: myLocale( loc )
, myCType( &std::use_facet<std::ctype<char> >( myLocale ) )
{
}
bool operator()( char ch ) const
{
return myCType->is( m, ch );
}
};
typedef Is<std::ctype_base::space> IsSpace;
添加额外的 typedef 是微不足道的,这样你就可以得到完整的 set,我发现添加一个IsNot
模板也很有用。 它 简单,它避免了所有周围的问题。
- 概念中的cv限定符需要表达式参数列表
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题
- 错误 没有与参数列表匹配的重载函数"getline"实例
- std::vector 没有重载函数的实例与参数列表匹配
- 模板参数列表中的 false 在模板初始化期间计算为什么?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 构造函数/函数声明参数列表中的统一初始化
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何将类成员方法的参数列表自动填充写入可变参数?
- 带有整数的变量参数列表
- 转发变量参数列表以模拟 std::thread
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- C++-将具有引用的长参数列表重构为结构
- 缺少别名模板C++参数列表
- C++如果两个模板函数都与参数列表匹配,将调用哪个模板
- "extern"声明以及带有和不带参数列表的类模板实例的后续定义
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 没有函数模板的实例与我不知道为什么的参数列表匹配
- 我可以使用宏自动构建参数列表吗?
- 类成员函数参数列表是否可以依赖于模板参数?