std::设置构造函数签名混淆

std::set constructor signature confusion

本文关键字:构造函数 设置 std      更新时间:2023-10-16

我正在阅读C++入门,了解如何定义set。当我浏览cpp偏好关于set时,我对set的类和构造函数签名感到困惑。

从文本:

bool compareIsbn(){....}
multiset<Sales_data, decltype(compareIsbn) *> bookstore(compareIsbn)

文本 1:

要使用我们自己的操作,我们必须用两种类型定义多集: 键类型Sales_data和比较类型(函数( 可以指向compareIsbn的指针类型。 当我们定义对象时 在此类型中,我们提供一个指向我们打算使用的操作的指针。在 在这种情况下,我们提供了一个指向compareIsbn的指针:

所以从text1来看,我似乎需要在set<Class A, a function pointer>中放置一个函数指针

但是当我查找 cpp首选项时,"签名"(不确定它是否是正确的词(是:

template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;

问题1:所以第二个参数应该是class


文本 2:

我们可以编写compareIsbn而不是&compareIsbn作为构造函数 参数,因为当我们使用函数的名称时,它是 如果需要,自动转换为指针。我们可以有 具有相同效果的书面&compareIsbn

同样来自集合的cppreference构造函数(我认为教科书使用的是第一个构造函数(:

set();
explicit set( const Compare& comp, 
const Allocator& alloc = Allocator() );

问题 2:构造函数不需要函数引用吗?从哪里说它需要一个函数指针


需要一些帮助来理解"签名",提前感谢:D。

附注:

  1. 教科书以multiset为例,但setmultiset的"签名"却大同小异。
  2. 我不知道const Allocator& alloc = Allocator()是什么意思,但我想也许这是自动完成的事情?我暂时可以忽略它。

这有点混乱,但相当接近正确。

使用"class"指定的类型模板参数是一个历史/语法怪癖;这实际上表明该参数是一种类型。"typename"也是合法的,并且在语义上是相同的:

template<typename T>
struct Foo {
T thing;
}
template<class T>
struct Bar {
T thing;
}
// Foo and Bar will work identically

在本书的示例中,传递给模板的类型是"指向 CompareIsbn 类型的指针">


至于你的第二个问题,请记住Compare是一种类型:

template<typename T>
void Foo(const T& object) { ... }

模板函数 Foo 希望传递对 T 的常量引用。如果 T 是指针类型,则它需要对指针的 const 引用:

Thing* bar = new Thing();
Foo<Thing*>(bar); // This instantiation of the template has signature void (const Thing*&)

在本书的示例中,Comparedecltype(CompareIsbn)*的,因此您必须const decltype(CompareIsbn)*&传递给构造函数。


CPP首选项有一个页面,详细说明了用于set模板中Compare参数的类型的要求,您可能会发现该页面很有用。简短的版本是,它只需要是一种类型,以便此代码正常工作:

// Given Compare comp
// Given Key a, b
bool b = comp(a, b);

然后,对于调用operator()必须如何行为,有一些要求。

函数指针将在该上下文中工作,因此没问题。但std::function,或任何以正确行为实施operator()的类型也是如此。模板声明中的= std::less<Key>位是将Compare参数的默认值设置为此类对象,该对象只是尝试使用Key::operator<

Allocator参数也是一个类似函数的对象,用于在必要时创建新的Key对象。您很少需要提供显式分配器;默认实现在几乎所有情况下都可以正常工作。

所以

从text1来看,我似乎需要将函数指针放在set<Class A, a function pointer>

差一点。是的,您需要提供指向构造函数的函数指针,但文本告诉您需要提供一个类型作为模板的参数。所述类型必须是函数指针的类型。

所以第二个参数应该是一个类吗?

第二个参数必须是类型。模板类型参数由两个关键字之一指定,classtypename。但它们的意思是一样的,你提供的参数必须是一个类型。

构造函数不需要函数引用吗?

不,它需要引用您作为参数给出的类型的对象。由于您提供函数指针作为类型,因此它需要对函数指针的引用。这就是它最终得到的。