如何在 C++03 中使用自定义谓词调用 std::unique?
How to call std::unique with custom predicate in C++03?
我看到了如何在 C++11 中执行此操作的示例:
std::unique(v.begin(), v.end(), [](float l, float r)
{
return std::abs(l - r) < 0.01;
});
然而,这对我来说在 C++03 中失败了:
error: template argument for 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)' uses local type 'CRayTracer::myFunc()::<lambda(float, float)>'
我如何在 C++03 中执行此操作?我认为 Lambdas 可能已经存在,并且存在 functors/function 个对象,对吧?只是寻找一个简单的解决方案,不需要可扩展 - 它只会在这里使用。
这是一个代码示例,我无法编译它:
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
struct approx_equal
{
bool operator()(float l, float r)
{
return std::abs(l - r) < 0.01;
}
};
approx_equal f;
std::unique(v.begin(), v.end(),f);
}
这是它产生的错误:
testUnique.cpp: In function 'int main()':
testUnique.cpp:21:37: error: no matching function for call to 'unique(std::vector<float>::iterator, std::vector<float>::iterator, main()::approx_equal&)'
21 | std::unique(v.begin(), v.end(),f);
| ^
In file included from C:/msys64/mingw64/include/c++/9.2.0/algorithm:62,
from testUnique.cpp:3:
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:995:5: note: candidate: 'template<class _FIter> _FIter std::unique(_FIter, _FIter)'
995 | unique(_ForwardIterator __first, _ForwardIterator __last)
| ^~~~~~
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:995:5: note: template argument deduction/substitution failed:
testUnique.cpp:21:37: note: candidate expects 2 arguments, 3 provided
21 | std::unique(v.begin(), v.end(),f);
| ^
In file included from C:/msys64/mingw64/include/c++/9.2.0/algorithm:62,
from testUnique.cpp:3:
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:1025:5: note: candidate: 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)'
1025 | unique(_ForwardIterator __first, _ForwardIterator __last,
| ^~~~~~
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:1025:5: note: template argument deduction/substitution failed:
testUnique.cpp: In substitution of 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<float*, std::vector<float> >; _BinaryPredicate = main()::approx_equal]':
testUnique.cpp:21:37: required from here
testUnique.cpp:21:37: error: template argument for 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)' uses local type 'main()::approx_equal'
21 | std::unique(v.begin(), v.end(),f);
| ^
testUnique.cpp:21:37: error: trying to instantiate 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)'
这是我的一组标志:
g++ -c -g -O3 -Wp,-D_FORTIFY_SOURCE=2 -m64 -Wshadow -Wall -DMX_COMPAT_32 -fexceptions -fno-omit-frame-pointer -D__WIN32__ -std=c++03 testUnique.cpp -o testUnique.o
I think Lambdas may have already existed,
没有。 Lambda 已在 C++11 中引入。
... and functors/function objects existed, right?
仿函数只是带有 operator()
的对象,因此它们一直存在(尽管不确定术语 "functor" 何时真正为它们引入)。
对于正式的正确表达方式,我建议您参考其他参考资料,草率地说这个
auto f = [](float l, float r){
return std::abs(l - r) < 0.01;
};
f(0.1,0.2);
相当于
struct unnamed {
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
unnamed f;
f(0.1,0.2);
即你总是可以用手写的仿函数替换 lambda class。创建仿函数的实例并传递它而不是 lambda。
完整示例:
#include <iostream>
#include <vector>
#include <algorithm>
struct approx_equal{
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
int main(){
std::vector<float> v{1.0, 1.0, 3.5, 3.5 };
approx_equal f;
v.erase(std::unique(v.begin(), v.end(),f),v.end());
// sorry this is c++11, replace with iterator loop to see output pre-c++11
for (const auto& x : v) std::cout << x << " ";
}
PS:在 C++03 中,您不能在本地定义仿函数 class 然后将其用作模板参数(请注意,您没有明确地将其作为模板参数传递,但是 unique
必须根据您传入的参数推断其类型)。
C++03 中不存在 Lambda,它们是在 C++11 中引入的。
由于您的 lambda 示例不需要捕获值,您可以将其替换为简单的独立函数,不需要函子,例如:
#include <iostream>
#include <vector>
#include <algorithm>
bool approx_equal(float l, float r) {
return std::abs(l - r) < 0.01;
}
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
std::unique(v.begin(), v.end(), approx_equal);
}
但是,您也可以使用函子。在您尝试使用仿函数时,您只是在 main()
本身内部定义了仿函数类型,使其成为编译器抱怨的局部类型。相反,在全局范围内定义仿函数类型(您仍然可以使用局部变量来实例化该类型),例如:
#include <iostream>
#include <vector>
#include <algorithm>
struct approx_equal {
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
approx_equal f;
std::unique(v.begin(), v.end(), f);
// or:
// std::unique(v.begin(), v.end(), approx_equal{});
}
我看到了如何在 C++11 中执行此操作的示例:
std::unique(v.begin(), v.end(), [](float l, float r)
{
return std::abs(l - r) < 0.01;
});
然而,这对我来说在 C++03 中失败了:
error: template argument for 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)' uses local type 'CRayTracer::myFunc()::<lambda(float, float)>'
我如何在 C++03 中执行此操作?我认为 Lambdas 可能已经存在,并且存在 functors/function 个对象,对吧?只是寻找一个简单的解决方案,不需要可扩展 - 它只会在这里使用。
这是一个代码示例,我无法编译它:
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
struct approx_equal
{
bool operator()(float l, float r)
{
return std::abs(l - r) < 0.01;
}
};
approx_equal f;
std::unique(v.begin(), v.end(),f);
}
这是它产生的错误:
testUnique.cpp: In function 'int main()':
testUnique.cpp:21:37: error: no matching function for call to 'unique(std::vector<float>::iterator, std::vector<float>::iterator, main()::approx_equal&)'
21 | std::unique(v.begin(), v.end(),f);
| ^
In file included from C:/msys64/mingw64/include/c++/9.2.0/algorithm:62,
from testUnique.cpp:3:
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:995:5: note: candidate: 'template<class _FIter> _FIter std::unique(_FIter, _FIter)'
995 | unique(_ForwardIterator __first, _ForwardIterator __last)
| ^~~~~~
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:995:5: note: template argument deduction/substitution failed:
testUnique.cpp:21:37: note: candidate expects 2 arguments, 3 provided
21 | std::unique(v.begin(), v.end(),f);
| ^
In file included from C:/msys64/mingw64/include/c++/9.2.0/algorithm:62,
from testUnique.cpp:3:
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:1025:5: note: candidate: 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)'
1025 | unique(_ForwardIterator __first, _ForwardIterator __last,
| ^~~~~~
C:/msys64/mingw64/include/c++/9.2.0/bits/stl_algo.h:1025:5: note: template argument deduction/substitution failed:
testUnique.cpp: In substitution of 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate) [with _FIter = __gnu_cxx::__normal_iterator<float*, std::vector<float> >; _BinaryPredicate = main()::approx_equal]':
testUnique.cpp:21:37: required from here
testUnique.cpp:21:37: error: template argument for 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)' uses local type 'main()::approx_equal'
21 | std::unique(v.begin(), v.end(),f);
| ^
testUnique.cpp:21:37: error: trying to instantiate 'template<class _FIter, class _BinaryPredicate> _FIter std::unique(_FIter, _FIter, _BinaryPredicate)'
这是我的一组标志:
g++ -c -g -O3 -Wp,-D_FORTIFY_SOURCE=2 -m64 -Wshadow -Wall -DMX_COMPAT_32 -fexceptions -fno-omit-frame-pointer -D__WIN32__ -std=c++03 testUnique.cpp -o testUnique.o
I think Lambdas may have already existed,
没有。 Lambda 已在 C++11 中引入。
... and functors/function objects existed, right?
仿函数只是带有 operator()
的对象,因此它们一直存在(尽管不确定术语 "functor" 何时真正为它们引入)。
对于正式的正确表达方式,我建议您参考其他参考资料,草率地说这个
auto f = [](float l, float r){
return std::abs(l - r) < 0.01;
};
f(0.1,0.2);
相当于
struct unnamed {
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
unnamed f;
f(0.1,0.2);
即你总是可以用手写的仿函数替换 lambda class。创建仿函数的实例并传递它而不是 lambda。
完整示例:
#include <iostream>
#include <vector>
#include <algorithm>
struct approx_equal{
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
int main(){
std::vector<float> v{1.0, 1.0, 3.5, 3.5 };
approx_equal f;
v.erase(std::unique(v.begin(), v.end(),f),v.end());
// sorry this is c++11, replace with iterator loop to see output pre-c++11
for (const auto& x : v) std::cout << x << " ";
}
PS:在 C++03 中,您不能在本地定义仿函数 class 然后将其用作模板参数(请注意,您没有明确地将其作为模板参数传递,但是 unique
必须根据您传入的参数推断其类型)。
C++03 中不存在 Lambda,它们是在 C++11 中引入的。
由于您的 lambda 示例不需要捕获值,您可以将其替换为简单的独立函数,不需要函子,例如:
#include <iostream>
#include <vector>
#include <algorithm>
bool approx_equal(float l, float r) {
return std::abs(l - r) < 0.01;
}
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
std::unique(v.begin(), v.end(), approx_equal);
}
但是,您也可以使用函子。在您尝试使用仿函数时,您只是在 main()
本身内部定义了仿函数类型,使其成为编译器抱怨的局部类型。相反,在全局范围内定义仿函数类型(您仍然可以使用局部变量来实例化该类型),例如:
#include <iostream>
#include <vector>
#include <algorithm>
struct approx_equal {
bool operator()(float l, float r) {
return std::abs(l - r) < 0.01;
}
};
int main(){
std::vector<float> v;
v.push_back(1.0);
v.push_back(1.0);
v.push_back(3.5);
v.push_back(3.5);
approx_equal f;
std::unique(v.begin(), v.end(), f);
// or:
// std::unique(v.begin(), v.end(), approx_equal{});
}