比较函数对象的类型签名
Type signature of comparison function object
如何在方法签名中使用比较函数对象类型?例如,这一切都很好:
struct compInt {
bool operator() (const int a, const int b) { return a < b; }
};
set<int,compInt> s1;
// Actually this is no good, but removing it would obfuscate
// the accepted answer:
set<int> s2(compInt);
[最后一个编译不过是函数声明,s2原来不是容器]。
但我想这样做:
void func (____ x)
{
set<int> s(x);
}
我不想这样做:
template<typename C>
void func (C& c)
{
set<int> s(c);
}
而function<bool(const int,const int)>
不工作。我尝试将 compInt::operator()
设为虚拟,这样我就可以这样做:
void func (compInt& ci)
并传入派生对象,但实际上 set<int> s(ci)
无法编译(对此我非常感激,因为这是一个可怕的 hack)。
set<int> s1(compInt);
这声明了一个 return 类型为 set<int>
的函数。
set<int> s(x);
这声明了一个 set<int>
类型的局部变量。比较器类型不是从参数推导出来的,而是使用默认模板参数。因此,compInt
不用作比较器,因此您不能将 compInt
的实例传递给构造函数。
您可以使用:
void func (compInt x)
{
std::set<int,compInt> s(x);
I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
多态比较器会很成问题。 Set 按值存储对象,因此通过引用传递给函数无济于事。您需要使用类型擦除:定义一个包装器比较器,它将多态比较器作为构造函数参数,将其存储在动态存储中,并将调用运算符委托给存储的多态比较器。然后使用包装器类型作为集合的模板参数。
Eeroiki 让我朝着正确的方向前进。我最终确定的是这个(注意要比较的对象实际上不是整数,并且可以对它们应用各种比较器)。
using intCompFunc = std::function<bool(const int,const int)>
struct compInt {
intCompFunc comp;
bool operator() (const int a, const int b) const {
return comp(a, b);
}
void foo (intCompfunc icf)
{
compInt ci { icf };
std::set<int,compInt> s1(ci);
}
这意味着用户可以传入任何类型的函子,例如。一个拉姆达:
foo([] (const int a, const int b) { return a < b; });
我的困惑源于为什么一开始不是这样,我认为这确实是一个历史问题(编写 STL 时还没有 C++11 仿函数)。 OTOH,使用基本类型而不是模板参数确实会引入一些运行时开销。
如何在方法签名中使用比较函数对象类型?例如,这一切都很好:
struct compInt {
bool operator() (const int a, const int b) { return a < b; }
};
set<int,compInt> s1;
// Actually this is no good, but removing it would obfuscate
// the accepted answer:
set<int> s2(compInt);
[最后一个编译不过是函数声明,s2原来不是容器]。
但我想这样做:
void func (____ x)
{
set<int> s(x);
}
我不想这样做:
template<typename C>
void func (C& c)
{
set<int> s(c);
}
而function<bool(const int,const int)>
不工作。我尝试将 compInt::operator()
设为虚拟,这样我就可以这样做:
void func (compInt& ci)
并传入派生对象,但实际上 set<int> s(ci)
无法编译(对此我非常感激,因为这是一个可怕的 hack)。
set<int> s1(compInt);
这声明了一个 return 类型为 set<int>
的函数。
set<int> s(x);
这声明了一个 set<int>
类型的局部变量。比较器类型不是从参数推导出来的,而是使用默认模板参数。因此,compInt
不用作比较器,因此您不能将 compInt
的实例传递给构造函数。
您可以使用:
void func (compInt x)
{
std::set<int,compInt> s(x);
I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
多态比较器会很成问题。 Set 按值存储对象,因此通过引用传递给函数无济于事。您需要使用类型擦除:定义一个包装器比较器,它将多态比较器作为构造函数参数,将其存储在动态存储中,并将调用运算符委托给存储的多态比较器。然后使用包装器类型作为集合的模板参数。
Eeroiki 让我朝着正确的方向前进。我最终确定的是这个(注意要比较的对象实际上不是整数,并且可以对它们应用各种比较器)。
using intCompFunc = std::function<bool(const int,const int)>
struct compInt {
intCompFunc comp;
bool operator() (const int a, const int b) const {
return comp(a, b);
}
void foo (intCompfunc icf)
{
compInt ci { icf };
std::set<int,compInt> s1(ci);
}
这意味着用户可以传入任何类型的函子,例如。一个拉姆达:
foo([] (const int a, const int b) { return a < b; });
我的困惑源于为什么一开始不是这样,我认为这确实是一个历史问题(编写 STL 时还没有 C++11 仿函数)。 OTOH,使用基本类型而不是模板参数确实会引入一些运行时开销。