C++ 比较函数对象的类型签名

C++ 比较函数对象的类型签名,c++,functor,C++,Functor,如何在方法签名中使用比较函数对象类型?这一切都很好: 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(

如何在方法签名中使用比较函数对象类型?这一切都很好:

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);  
并传入派生对象,但事实上,
sets(ci)
随后无法编译(我几乎对此表示感谢,因为这是一个可怕的黑客行为)

我尝试将compInt::operator()设置为虚拟,以便执行以下操作:

void func (compInt& ci)
void func (compInt& ci)

多态性比较器会有很大的问题。Set按值存储对象,因此通过引用传递到函数将没有帮助。您需要使用类型擦除:定义一个包装器比较器,它将多态比较器作为构造函数参数,存储在动态存储器中,并将调用运算符委托给存储的多态比较器。然后使用包装器类型作为集合的模板参数。

Eeroiki让我朝着正确的方向前进。我最终确定了这一点(注意,要比较的对象实际上不是int,可以对它们应用多种比较器)

使用intCompFunc=std::function
结构compInt{
intCompFunc comp;
布尔运算符(){
返回薪酬(a、b);
}
void foo(intCompfunc icf)
{ 
compInt ci{icf};
std::集s1(ci);
}    
这意味着用户可以传入任何类型的函子,例如lambda:

foo([] (const int a, const int b) { return a < b; }); 
foo([](常量inta,常量intb){返回a

我的困惑源于为什么一开始不是这样,我认为这确实是一个历史问题(STL编写时没有C++11函子).OTOH,使用基类型而不是模板参数确实会带来一些运行时开销。

?我不明白。您想执行
typedef int\uuuuuuuu;
?所以您想要
template void func(){set s;}
我不想这样做:
为什么?
和函数…不起作用
-什么是
函数
?是
函数
的一个拼写错误,如果
函数编译失败
-请发布“编译失败”的完整代码包括相关的
#包括
s、错误消息、编译器版本、选项等。请创建一个。您希望比较函数对象是动态的吗?您可以有一个比较函数对象包装std::function并在内部调用它。请下次(您仍可以在此处执行)包括a和错误消息。@BogdanPetrica我想我希望情况已经如此,即“比较对象”,它在概念上定义得非常清楚,可以有一个具体的签名。我想我现在明白了为什么不能,但这似乎是语言的一个历史负担,因为这些不仅仅是直函子——如果需要维护状态,您仍然可以使用comparator obj,因为它们适合
函数
,但我猜不会无状态函数指针将是更常见的情况。不确定是否理解了这个注释,但也许你正在寻找::指定任何其他的限制都会太过严格。这样命名的要求已经在C++中很长时间以来存在,但是只有C++ 20中的概念才是真正的一流公民。“…无法将
x
传递给构造函数"我最近才读到关于类型推断的新特性,所以我不确定它是否适用于C++17及更高版本,因为比较器的类型是从
x
?@idclev463035818推导出来的。如果set有合适的类型推断指南,它可能会起作用。它显然不起作用。我不知道为什么。在写了t他提出了这个问题,但我仍然决定为C++中纯概念性但可明确定义的“比较对象”获得一个全面的类型签名……现在我意识到这是因为类的类型只能是类本身或基,而
set
是一个模板,所以“比较对象”只是由行为含蓄地定义。我猜这应该是显而易见的……问题是,声称一切都会好起来,这有点让人困惑,所以@idclev463035818我考虑了一下,我认为因为模板参数有一个默认值,所以添加一个演绎指南理论上可以打破通过不同类型但可转换的比较器的现有代码。这不是一个真正的历史问题。请注意,
std::function
是一个非常讨厌的东西。它给你一个可以容纳所有类型的可调用项。这是有代价的,通常您不需要它。例如,如果只需要一种特定类型的比较器,那么就不需要
std::function
的开销
set<int> s1(compInt);
set<int> s(x);
void func (compInt x)
{
    std::set<int,compInt> s(x);
void func (compInt& ci)
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; });