C ++模板和duck typing之间的关系是什么?

时间:2011-08-03 07:57:02

标签: c++ templates duck-typing

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

7 个答案:

答案 0 :(得分:70)

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

如果某些内容不正确(例如,复制构造函数丢失),则编译失败。 当你用一个函数调用一个函数时,真正的ducktyping中的对应物是失败的 非鸭型。在这里,它将在运行时发生。

答案 1 :(得分:13)

鸭子打字意味着,“如果它像鸭子一样呱呱叫,像鸭子一样走路,那就是鸭子”。它在计算机科学中没有正式的定义供我们比较C ++。

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

此外,由于模板参数推导,在C ++中您可以尝试传递任何旧对象,编译器将确定它是否可以实例化函数模板。

一个区别是在C ++中,如果参数不嘎嘎,那么编译器对象。在Python中,只有运行时对象(并且只有在实际调用函数时,如果代码中存在条件)。这是对象/类型所需接口性质的差异 - 在C ++中,模板要求特定表达式有效,要么不需要。在Python中,必要的有效表达式可以依赖于先前必需表达式的运行时值。所以在Python中你可以要求一个对象大声或悄悄地嘎嘎叫,如果它大声嘎嘎叫它也需要走路。在C ++中,您可以通过条件dynamic_cast来实现,如果卷是编译时常量,您可以进行模板特化,但是您不能使用静态类型来说鸭子只需要走路quack_volume()返回loud。当然,在Python中,所需的接口可能并不是“必需的” - 如果不存在方法,则行为是抛出异常,如果发生这种情况,可能会记录并保证调用者的行为。

由您决定是否定义“duck typing”,以便这种差异意味着C ++没有它。

答案 2 :(得分:12)

  

对我来说,C ++模板使用了鸭子打字的想法,这是对的吗?

不,C ++模板用于实现通用代码。也就是说,如果您的代码可以使用多种类型,则不必为每种类型复制它。像std::vectorstd::list这样的事情就是明显的例子。 C ++模板have been abused做其他事情,但通用性是最初的意图。

  

是否表示模板类或方法中引用的所有泛型类型   是鸭型?

不,它们只是“正常”类型,就像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 ++中获得的鸭子打字很接近。

答案 3 :(得分:4)

是的,有点 - 例如,如果类型X具有AddRef()Release()QueryInterface()方法以及适当的签名,则可以将其用作{{{1}的COM对象1}}模板类。但这并不是完整的鸭子类型 - 对参数仍然强制执行类型检查。

答案 4 :(得分:4)

不完全是。 Duck类型(动态类型样式)永远不会产生编译时类型错误,因为它们没有任何类型。使用模板,在实例化模板之前,您没有类型。一旦你这样做,变量有不同的类型,你确实会遇到编译时错误。

此外,对于duck类型,您可以将一个变量指向不同类型的对象,因为变量没有类型。这对模板来说是不可能的 - 一旦你实例化它们,变量只有一个特定的类型。

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

答案 5 :(得分:2)

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

答案 6 :(得分:1)

维基百科covers this distinction