模板C++和鸭子打字之间有什么关系?

What's the relationship between C++ template and duck typing?

本文关键字:什么 关系 之间 C++ 鸭子 模板      更新时间:2023-10-16

对我来说,c++模板使用了duck typing的思想,这对吗?这是否意味着模板类或方法中引用的所有泛型类型都是鸭型?

对我来说,c++模板是duck类型的编译时版本。编译器将编译例如类和只要你的鸭子拥有所有需要的类型,它将实例化一个类。

如果某件事不正确(例如:缺少复制构造函数)则编译失败。在实际的ducktyping中,当您使用non-duck类型。这里它会在运行时发生。

鸭子打字的意思是,"如果它像鸭子一样叫,像鸭子一样走,那么它就是一只鸭子"。在计算机科学中,它没有一个正式的定义供我们比较c++。

当然,

c++与(例如)Python并不完全相同,但它们都有隐式定义接口的概念。作为Python函数参数使用的对象所需的接口是函数对它所做的任何操作。作为c++模板实参的类型所需的接口是模板对该类型的对象所做的任何操作。这就是相似之处,也是评估c++模板的依据。

此外,由于模板参数演绎,在c++中你可以尝试传递任何旧对象,编译器会判断它是否可以实例化函数模板。

一个不同之处在于,在c++中,如果实参没有乱叫,则编译器对象。在Python中,只有运行时对象(并且只有在实际调用函数时,如果代码中有条件)。这是对象/类型所要求的接口性质的不同——在c++中,模板要么要求特定表达式有效,要么不要求。在Python中,必要的有效表达式可以依赖于早期必要表达式的运行时值。所以在Python中,你可以请求一个叫得很大声或很安静的对象,如果它叫得很大声,它也需要走路。在c++中,你可以通过一个条件的dynamic_cast来做到这一点,如果volume是一个编译时常数,你可以做模板特化,但是你不能使用静态类型来说鸭子只需要在quack_volume()返回loud时才需要行走。当然,在Python中,所需的接口可能不是真正的"必需"——如果方法不存在,行为就是抛出异常,如果发生这种情况,可能会记录并保证调用者的行为。

取决于你是否定义了"duck typing",所以这个区别意味着c++没有它。

对我来说,c++模板使用了duck typing的思想,这对吗?

不,c++模板用于实现泛型代码。也就是说,如果您的代码可以使用多种类型,则不必为每种类型复制代码。像std::vectorstd::list这样的东西是这方面的明显例子。c++模板被滥用于做其他事情,但泛型是它的初衷。

是否指模板类或方法中引用的所有泛型类型你是鸭子型的吗?

不,它们只是"正常"类型,就像c++中的其他类型一样。它们只是在模板实际实例化之前是不知道的。

然而,模板可以用来实现一些的东西,比如 duck typing。迭代器就是一个例子。考虑这个函数:
template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
                        OutputIterator result)
{
    while (first!=last) *result++ = *first++;
    return result;
}
注意copy函数可以接受任何类型的参数,只要它实现了不等式操作符、解引用操作符和后缀自增操作符。这可能是您在c++中最接近duck typing的地方。

不完全是。Duck类型(动态类型风格)永远不会产生编译时类型错误,因为它们根本没有任何类型。对于模板,在实例化模板之前没有类型。一旦这样做了,变量就有了不同的类型,并且确实会得到编译时错误。

同样,对于duck类型,您可以让一个变量指向不同类型的对象,因为变量没有类型。这在模板中是不可能的——一旦实例化了它们,变量就只有一个特定的类型。

它们是相似的,因为约束是隐式的:只检查实际使用的特性。与多态指针相反,实际类型并不重要。

是的,有点-例如,如果类型X具有AddRef(), Release()QueryInterface()方法并具有适当的签名,则可以将其用作CComPtr模板类的COM对象。但是这并不是完全的duck类型—仍然强制对参数进行类型检查。

不,这是一个不同的概念。Duck类型是一种查找动态类型容器类型的方法。c++模板不是动态类型的,它们是用特定类型实例化的。

维基百科涵盖了这一区别。