考虑使用以下函数来比较vector
的两个T
,并使用T.operator==
函数验证它们是否相同。
template<typename T>
bool Verify(const std::vector<T>& a, const std::vector<T>& b)
{
if (a.size() != b.size())
return false;
for (int ii=0; ii<a.size(); ii++)
if (!(a[ii] == b[ii]))
return false;
return true;
}
问题是T
可能不包含operator==
因此我想更新Verify
函数,因此它接受比较函数作为参数。这样,用户可以调用提供自定义比较功能的函数。
类似的东西:
template<typename T>
bool Verify(const std::vector<T>& a, const std::vector<T>& b, std:function<bool(T,T)> isEqual)
问题是:
我可以将isEqual
的默认值设置为T.operator==
吗?
如果是,怎么样?
如果不是,我有什么选择。
答案 0 :(得分:4)
您可以将标准比较仿函数std::equal_to()
设置为默认值:
template<typename T>
bool Verify( const std::vector<T>& a,
const std::vector<T>& b,
std::function<bool(const T&,const T&)> isEqual = std::equal_to<T>()
);
答案 1 :(得分:2)
STL
和其他人采用的一般方法是将比较仿函数作为默认的附加模板参数传递,但可以覆盖。这是一个例子:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <class T, class Compare = std::equal_to<T>>
bool equal(
const std::vector<T>& lhs,
const std::vector<T>& rhs,
Compare comp = {}) // take comparison operator, default where appropriate
{
if(lhs.size() != rhs.size())
return false;
for(size_t x = 0, e = lhs.size(); x < e; ++x)
{
if(!comp(lhs[x], rhs[x]))
return false;
}
return true;
}
bool false_equality(int x, int y)
{
return false;
}
int main()
{
std::vector<int> a{1, 2, 3, 4};
std::vector<int> b{1, 2, 3, 4};
cout << equal(a, b) << " but " << equal(a, b, false_equality) << "\n";
return 0;
}
答案 2 :(得分:1)
std::function
对象实际上只能与nullptr
进行比较,也可以使用nullptr
进行构建。
这意味着您可以设置默认参数值nullptr
并与之进行比较,以查看是否应使用对象相等功能。
答案 3 :(得分:1)
Manu343726给出了正确的答案,使用std::equal_to<>
仿函数。在那个答案中不明显的是为什么你不想直接绑定运算符。
在C ++中,重载运算符(在大多数情况下)可以作为第一个参数的成员函数或作为自由函数实现。该语言旨在通过查找给定运算符是以某种方式定义,还是以某种方式定义(对于基本类型)来解析a == b
。另一方面,当您尝试手动获取操作员的地址时,您需要知道如何定义操作符(如果它是真正定义的)。
将isEqual的默认值设置为T.operator == (正确的语法为:&T::operator==
),您将只能使用默认参数operator==
被定义为成员函数的那些类型,但对于定义为自由函数的类型,它将失败。
如果你尝试使用自由函数版本会发生同样的事情,除了在这种情况下更糟糕,因为你甚至不知道运算符定义在哪个命名空间(你不能以编程方式提取一个名称空间)类型)。参数相关查找不适用于获取函数的地址
运算符在该语言中是特殊的,并且有一些特殊规则旨在促进代码中运算符的定义(自由函数/成员函数)和使用(ADL),但这些规则不应该取适用于取得经营者的地址。如果你需要绑定一个运算符,那么简单的答案就是创建一个帮助器类型调用运算符然后绑定它。
答案 4 :(得分:0)
您可以使用函数重载并具有这两种功能。一个人会把一个函数作为它的最后一个参数,而另一个函数会少一个参数。使用一个参数的函数调用另一个调用另一个传递operator ==作为最后一个参数。