错误 C2914:排序函数无法识别要使用哪个版本的重载谓词
Error C2914: sort function unable to identify which version of an overloaded predicate to use
我最近开始尝试自学 C++,并且是董事会的新手。我创建了一个名为 permuted_index 的支柱,以及一个名为 perm_index 的 permuted_index 对象矢量。
我编写了一个名为 "stringCompare" 的重载谓词,用于与排序函数一起对字符串向量或 permuted_index 对象向量进行排序。但是,当我尝试 运行 我的程序出现错误 C2914 - 据我所知,这意味着排序函数无法识别要使用的 stringCompare 版本。
我已经看了好几天了,完全被难住了!我可以通过注释掉谓词的一个版本来强制我的程序工作,但我真的很想了解底层程序并希望得到任何帮助。我已经提供了我认为可以帮助任何人在下面查看此内容的所有内容,但如果您需要任何更多信息,请告诉我。
这是置换索引支柱;
struct permuted_index{
std::string word ;
std::vector<std::string>::size_type line ;
std::string::size_type position ;
std::vector<std::string> full_line ;
std::vector<std::string> rotated_line ;
std::string before_word ;
std::string after_word ; };
这是重载谓词;
#include <string>
#include <vector>
#include "split.h"
#include "Permuted_index.h"
using std::string ;
using std::vector ;
bool stringCompare(const string& x, const string& y) {
vector<string> p ;
vector<string> q ;
p = split(x) ;
q = split(y) ;
return p[0] < q[0] ;
}
bool stringCompare(const permuted_index& x, const permuted_index& y){
return x.rotated_line[0] < y.rotated_line[0] ;
}
这是上面调用的split函数;
vector<string> split(const string& s)
{
vector<string> ret ;
typedef string::size_type string_size ;
string_size i = 0 ;
while(i != s.size())
{
while(i != s.size() && isspace(s[i]))
{
++i ;
}
string_size j = i ;
while(j != s.size() && !isspace(s[j]))
{
++j ;
}
if(i != j)
{
ret.push_back(s.substr(i, j-i)) ;
i = j ;
}
}
return ret ;
}
我的 main() 程序中导致错误的行是;
sort(perm_index.begin(), perm_index.end(), stringCompare) ;
准确的错误信息是:
error C2914: 'std::sort' : cannot deduce template argument as function argument is ambiguous
尝试以下方法
sort(perm_index.begin(), perm_index.end(),
static_cast<bool(*)( const permuted_index &, const permuted_index & )>(stringCompare) );
出于某种原因,使用强制转换对我来说似乎有点不确定。但这有效:
void foo(std::vector<permuted_index> &pi)
{
using Compare = bool (*)(const permuted_index &, const permuted_index&);
Compare cmp = stringCompare;
std::sort(pi.begin(), pi.end(), cmp);
}
这声明了一个类型别名,Compare
。
在 C++ 11 之前,这是通过所谓的 typedef
完成的,如:
typedef bool (*Compare)(const permuted_index &, const permuted_index &);
这些都只是说 Compare
是一个函数的名称,它接受两个 permuted_index
对象和 return 一个 bool
。 (从技术上讲,Compare
是指向函数的指针,但函数名称本身也是指针。)函数类型名称的 C/C++ 语法并不是最容易解析的语法,但如果您阅读 typedef
从内到外它以某种左右顺序("spiral" 规则)表示 Compare
是一个指针(星号),指向一个函数接受两个 permuted_index
引用(右边包含引用声明的括号)和 returning bool
)你可以找到 a nice SO description of these topics here and there are various tutorials on function pointer syntax (evidence in and of itself that it isn't the simplest aspect of C/C++) around the web, such as this article that explains the spiral rule.
无论如何,Compare
是一个函数的别名,该函数正是 sort
在对 permuted_index
对象进行排序时期望比较器使用的类型。然后我们声明一个指针实例 cmp
指向 stringCompare
。编译器现在可以准确地知道 cmp
的类型,因此对于我们可以将哪个 stringCompare
分配给 cmp
没有歧义。
另外,cmp
是一个指针,你实际上可以写
Compare cmp = &stringCompare;
在 C++ 中,函数名称本身 "decays" 指向指向该函数的指针,因此这是多余的,我在示例中将其省略。
另一种方法是使用内联 lambda。 Lambda 是该语言的一个新部分,它允许您就地声明一个函数。对于调用算法时通常只使用一次的比较器之类的东西,这是一种非常有用的语法。与函数指针一样,语法需要一点时间来适应。 Here is a nice SO article on the subject. 基本上 []
表示这是一个简单的 lambda(不是任何类型的 "closure"),后面是 lambda 的参数,然后是它的主体。 (您可以选择在参数之后立即将 return 类型声明为
[](const permuted_index &, const permuted_index &) -> bool { ... }
但这通常不是必需的,因为编译器可以从函数体中推断出类型。)
无论如何,与上面的 typedef
一样,这种方法有效,因为 lambda 已经声明了参数是什么,所以将选择正确的 stringCompare
,并且 lambda 的类型是显而易见的编译器,因此不会混淆使用哪种函数类型来计算 sort
.
中的第二个模板类型
void bar(std::vector<permuted_index> &pi)
{
std::sort(pi.begin(), pi.end(),
[](const permuted_index &a, const permuted_index &b)
{ return stringCompare(a,b); });
}
我认为问题在于 Compare
模板参数完全独立于被比较的类型 - 目前库无法指定其类型应具有比较签名在被排序的两种值类型之间。 (虽然我不确定为什么 SFINAE 不消除使用第一个重载的可能性。)
我最近开始尝试自学 C++,并且是董事会的新手。我创建了一个名为 permuted_index 的支柱,以及一个名为 perm_index 的 permuted_index 对象矢量。
我编写了一个名为 "stringCompare" 的重载谓词,用于与排序函数一起对字符串向量或 permuted_index 对象向量进行排序。但是,当我尝试 运行 我的程序出现错误 C2914 - 据我所知,这意味着排序函数无法识别要使用的 stringCompare 版本。
我已经看了好几天了,完全被难住了!我可以通过注释掉谓词的一个版本来强制我的程序工作,但我真的很想了解底层程序并希望得到任何帮助。我已经提供了我认为可以帮助任何人在下面查看此内容的所有内容,但如果您需要任何更多信息,请告诉我。
这是置换索引支柱;
struct permuted_index{
std::string word ;
std::vector<std::string>::size_type line ;
std::string::size_type position ;
std::vector<std::string> full_line ;
std::vector<std::string> rotated_line ;
std::string before_word ;
std::string after_word ; };
这是重载谓词;
#include <string>
#include <vector>
#include "split.h"
#include "Permuted_index.h"
using std::string ;
using std::vector ;
bool stringCompare(const string& x, const string& y) {
vector<string> p ;
vector<string> q ;
p = split(x) ;
q = split(y) ;
return p[0] < q[0] ;
}
bool stringCompare(const permuted_index& x, const permuted_index& y){
return x.rotated_line[0] < y.rotated_line[0] ;
}
这是上面调用的split函数;
vector<string> split(const string& s)
{
vector<string> ret ;
typedef string::size_type string_size ;
string_size i = 0 ;
while(i != s.size())
{
while(i != s.size() && isspace(s[i]))
{
++i ;
}
string_size j = i ;
while(j != s.size() && !isspace(s[j]))
{
++j ;
}
if(i != j)
{
ret.push_back(s.substr(i, j-i)) ;
i = j ;
}
}
return ret ;
}
我的 main() 程序中导致错误的行是;
sort(perm_index.begin(), perm_index.end(), stringCompare) ;
准确的错误信息是:
error C2914: 'std::sort' : cannot deduce template argument as function argument is ambiguous
尝试以下方法
sort(perm_index.begin(), perm_index.end(),
static_cast<bool(*)( const permuted_index &, const permuted_index & )>(stringCompare) );
出于某种原因,使用强制转换对我来说似乎有点不确定。但这有效:
void foo(std::vector<permuted_index> &pi)
{
using Compare = bool (*)(const permuted_index &, const permuted_index&);
Compare cmp = stringCompare;
std::sort(pi.begin(), pi.end(), cmp);
}
这声明了一个类型别名,Compare
。
在 C++ 11 之前,这是通过所谓的 typedef
完成的,如:
typedef bool (*Compare)(const permuted_index &, const permuted_index &);
这些都只是说 Compare
是一个函数的名称,它接受两个 permuted_index
对象和 return 一个 bool
。 (从技术上讲,Compare
是指向函数的指针,但函数名称本身也是指针。)函数类型名称的 C/C++ 语法并不是最容易解析的语法,但如果您阅读 typedef
从内到外它以某种左右顺序("spiral" 规则)表示 Compare
是一个指针(星号),指向一个函数接受两个 permuted_index
引用(右边包含引用声明的括号)和 returning bool
)你可以找到 a nice SO description of these topics here and there are various tutorials on function pointer syntax (evidence in and of itself that it isn't the simplest aspect of C/C++) around the web, such as this article that explains the spiral rule.
无论如何,Compare
是一个函数的别名,该函数正是 sort
在对 permuted_index
对象进行排序时期望比较器使用的类型。然后我们声明一个指针实例 cmp
指向 stringCompare
。编译器现在可以准确地知道 cmp
的类型,因此对于我们可以将哪个 stringCompare
分配给 cmp
没有歧义。
另外,cmp
是一个指针,你实际上可以写
Compare cmp = &stringCompare;
在 C++ 中,函数名称本身 "decays" 指向指向该函数的指针,因此这是多余的,我在示例中将其省略。
另一种方法是使用内联 lambda。 Lambda 是该语言的一个新部分,它允许您就地声明一个函数。对于调用算法时通常只使用一次的比较器之类的东西,这是一种非常有用的语法。与函数指针一样,语法需要一点时间来适应。 Here is a nice SO article on the subject. 基本上 []
表示这是一个简单的 lambda(不是任何类型的 "closure"),后面是 lambda 的参数,然后是它的主体。 (您可以选择在参数之后立即将 return 类型声明为
[](const permuted_index &, const permuted_index &) -> bool { ... }
但这通常不是必需的,因为编译器可以从函数体中推断出类型。)
无论如何,与上面的 typedef
一样,这种方法有效,因为 lambda 已经声明了参数是什么,所以将选择正确的 stringCompare
,并且 lambda 的类型是显而易见的编译器,因此不会混淆使用哪种函数类型来计算 sort
.
void bar(std::vector<permuted_index> &pi)
{
std::sort(pi.begin(), pi.end(),
[](const permuted_index &a, const permuted_index &b)
{ return stringCompare(a,b); });
}
我认为问题在于 Compare
模板参数完全独立于被比较的类型 - 目前库无法指定其类型应具有比较签名在被排序的两种值类型之间。 (虽然我不确定为什么 SFINAE 不消除使用第一个重载的可能性。)