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

时间:2022-03-18 11:13:57

To me, C++ template used the idea of duck typing, is this right? Does it mean all generic types referenced in template class or method are duck type?

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

7 个解决方案

#1


13  

To me, C++ template used the idea of duck typing, is this right?

对我来说,c++ template使用了duck typing的概念,是这样吗?

No, C++ templates are used to implement generic code. That is, if you have code that can work with more than one type, you don't have to duplicate it for each type. Things like std::vector and std::list are obvious examples of this in action. C++ templates have been abused into doing other things, but genericity was the original intention.

不,c++模板用于实现通用代码。也就是说,如果您有可以使用多个类型的代码,那么您不必为每个类型复制它。例如std::vector和std::list是这方面的明显例子。c++模板已经被滥用到做其他事情,但是一般性是最初的意图。

Does it mean all generic types referenced in template class or method are duck type?

它是否意味着模板类或方法中引用的所有泛型类型都是鸭子类型?

No, they are just "normal" types just like every other type in C++. They are just not known until the template is actually instantiated.

不,它们只是“普通”类型,就像c++中的其他类型一样。直到模板被实例化,它们才被知道。

However, templates can be used to implement something like duck typing. Iterators are an example. Consider this function:

但是,模板可以用来实现类似鸭子类型的东西。迭代器是一个例子。考虑一下这个函数:

template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
                        OutputIterator result)
{
    while (first!=last) *result++ = *first++;
    return result;
}

Note that the copy function can accept arguments of any type, as along as it implements the inequality operator, the dereference operator, and the postfix increment operator. This is probably as close to duck typing as you'll get in C++.

注意,copy函数可以接受任何类型的参数,就像它实现不等式操作符、去引用操作符和后缀递增操作符一样。这可能是您在c++中遇到的最接近于duck typing的情况。

#2


59  

To me C++ templates are a compile-time version of duck typing. The compiler will compile e.g. Class and as long as your Duck has all needed types it will instantiate a class.

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

If something is not correct(e.g. copy constructor missing) the compilation fails. The counterpart in real ducktyping is a failure when you call a function with a non-duck type. And here it would occur at runtime.

如果某事是不正确的。复制构造函数丢失)编译失败。当您调用具有非duck类型的函数时,真正的ducktyping中的对应对象是失败的。它会在运行时发生。

#3


11  

Duck typing means, "if it quacks like a duck and walks like a duck, then it's a duck". It doesn't have a formal definition in computer science for us to compare C++ against.

Duck typing的意思是“如果它像鸭子一样嘎嘎叫,走路像鸭子,那就是鸭子。”在计算机科学中没有一个正式的定义来比较c++。

C++ is not identical to (for example) Python, of course, but they both have a concept of implicitly-defined interfaces. The interface required of an object used as a Python function argument is whatever the function does with it. The interface required of a type used as a C++ template argument is whatever the template does with objects of that type. That is the similarity, and that is the grounds on which C++ templates should be assessed.

当然,c++与(例如)Python不同,但是它们都有一个定义不明确的接口的概念。作为Python函数参数的对象所需的接口是函数对其做的任何事情。作为c++模板参数使用的类型所需的接口是模板对该类型的对象所做的任何事情。这就是相似之处,这也是评估c++模板的理由。

Furthermore, because of template argument deduction, in C++ you can attempt to pass any old object, and the compiler will figure out whether it can instantiate the function template.

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

One difference is that in C++, if the argument doesn't quack, then the compiler objects. In Python, only the runtime objects (and only if the function is actually called, if there are conditionals in the code). This is a difference in the nature of the interface demanded of an object/type - in C++ either the template requires that a particular expression is valid, or it doesn't require that. In Python, the necessary valid expressions can depend on the runtime values of earlier necessary expressions. So in Python you can ask for an object that either quacks loudly or quietly, and if it quacks loudly it needs to walk too. In C++ you can do that by a conditional dynamic_cast, and if the volume is a compile-time constant you could do it template specializations, but you can't use static typing to say that a duck only needs to walk if quack_volume() returns loud. And of course in Python the required interface may not really be "required" - behavior if a method isn't present is to throw an exception, and it might be possible to document and guarantee the caller's behavior if that happens.

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

Up to you whether you define "duck typing" so that this difference means C++ doesn't have it.

至于你是否定义了“duck typing”,这一区别意味着c++没有这个功能。

#4


4  

Not exactly. Duck types (dynamic type style) will never yield compile-time type errors because they just don't have any type. With templates, you don't have types until you instantiate the template. Once you do, variables have distinct types, and you will indeed get compile-time errors.

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

Also, with duck types, you can have one variable point to different types of objects, because variables just have no types. That's not possible with templates — once you instantiate them, variables have a single specific type.

另外,对于鸭子类型,您可以有一个指向不同类型对象的变量点,因为变量只是没有类型。对于模板来说,这是不可能的——一旦实例化了它们,变量就有了一个特定的类型。

They are similar, though, in that constraints are implicit: only the features actually used are checked. As opposed to, say, polymorphic pointers, the actual type doesn't matter.

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

#5


3  

Yes, sort of - for example if type X has AddRef(), Release() and QueryInterface() methods with appropriate signatures it can be used as a COM object with CComPtr template class. But this is not complete duck typing - type checking is still enforced for parameters.

是的,例如,如果类型X有AddRef()、Release()和QueryInterface()方法,并具有适当的签名,它可以作为一个COM对象使用CComPtr模板类。但这并不是完全的鸭子类型检查-仍然执行参数。

#6


2  

No, this is a different concept. duck typing is a method to find out the type of a dynamic typed container. C++ templates aren't dynamic typed, they get instantiated with a specific type.

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

#7


1  

Wikipedia covers this distinction.

*这种区别。

#1


13  

To me, C++ template used the idea of duck typing, is this right?

对我来说,c++ template使用了duck typing的概念,是这样吗?

No, C++ templates are used to implement generic code. That is, if you have code that can work with more than one type, you don't have to duplicate it for each type. Things like std::vector and std::list are obvious examples of this in action. C++ templates have been abused into doing other things, but genericity was the original intention.

不,c++模板用于实现通用代码。也就是说,如果您有可以使用多个类型的代码,那么您不必为每个类型复制它。例如std::vector和std::list是这方面的明显例子。c++模板已经被滥用到做其他事情,但是一般性是最初的意图。

Does it mean all generic types referenced in template class or method are duck type?

它是否意味着模板类或方法中引用的所有泛型类型都是鸭子类型?

No, they are just "normal" types just like every other type in C++. They are just not known until the template is actually instantiated.

不,它们只是“普通”类型,就像c++中的其他类型一样。直到模板被实例化,它们才被知道。

However, templates can be used to implement something like duck typing. Iterators are an example. Consider this function:

但是,模板可以用来实现类似鸭子类型的东西。迭代器是一个例子。考虑一下这个函数:

template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
                        OutputIterator result)
{
    while (first!=last) *result++ = *first++;
    return result;
}

Note that the copy function can accept arguments of any type, as along as it implements the inequality operator, the dereference operator, and the postfix increment operator. This is probably as close to duck typing as you'll get in C++.

注意,copy函数可以接受任何类型的参数,就像它实现不等式操作符、去引用操作符和后缀递增操作符一样。这可能是您在c++中遇到的最接近于duck typing的情况。

#2


59  

To me C++ templates are a compile-time version of duck typing. The compiler will compile e.g. Class and as long as your Duck has all needed types it will instantiate a class.

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

If something is not correct(e.g. copy constructor missing) the compilation fails. The counterpart in real ducktyping is a failure when you call a function with a non-duck type. And here it would occur at runtime.

如果某事是不正确的。复制构造函数丢失)编译失败。当您调用具有非duck类型的函数时,真正的ducktyping中的对应对象是失败的。它会在运行时发生。

#3


11  

Duck typing means, "if it quacks like a duck and walks like a duck, then it's a duck". It doesn't have a formal definition in computer science for us to compare C++ against.

Duck typing的意思是“如果它像鸭子一样嘎嘎叫,走路像鸭子,那就是鸭子。”在计算机科学中没有一个正式的定义来比较c++。

C++ is not identical to (for example) Python, of course, but they both have a concept of implicitly-defined interfaces. The interface required of an object used as a Python function argument is whatever the function does with it. The interface required of a type used as a C++ template argument is whatever the template does with objects of that type. That is the similarity, and that is the grounds on which C++ templates should be assessed.

当然,c++与(例如)Python不同,但是它们都有一个定义不明确的接口的概念。作为Python函数参数的对象所需的接口是函数对其做的任何事情。作为c++模板参数使用的类型所需的接口是模板对该类型的对象所做的任何事情。这就是相似之处,这也是评估c++模板的理由。

Furthermore, because of template argument deduction, in C++ you can attempt to pass any old object, and the compiler will figure out whether it can instantiate the function template.

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

One difference is that in C++, if the argument doesn't quack, then the compiler objects. In Python, only the runtime objects (and only if the function is actually called, if there are conditionals in the code). This is a difference in the nature of the interface demanded of an object/type - in C++ either the template requires that a particular expression is valid, or it doesn't require that. In Python, the necessary valid expressions can depend on the runtime values of earlier necessary expressions. So in Python you can ask for an object that either quacks loudly or quietly, and if it quacks loudly it needs to walk too. In C++ you can do that by a conditional dynamic_cast, and if the volume is a compile-time constant you could do it template specializations, but you can't use static typing to say that a duck only needs to walk if quack_volume() returns loud. And of course in Python the required interface may not really be "required" - behavior if a method isn't present is to throw an exception, and it might be possible to document and guarantee the caller's behavior if that happens.

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

Up to you whether you define "duck typing" so that this difference means C++ doesn't have it.

至于你是否定义了“duck typing”,这一区别意味着c++没有这个功能。

#4


4  

Not exactly. Duck types (dynamic type style) will never yield compile-time type errors because they just don't have any type. With templates, you don't have types until you instantiate the template. Once you do, variables have distinct types, and you will indeed get compile-time errors.

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

Also, with duck types, you can have one variable point to different types of objects, because variables just have no types. That's not possible with templates — once you instantiate them, variables have a single specific type.

另外,对于鸭子类型,您可以有一个指向不同类型对象的变量点,因为变量只是没有类型。对于模板来说,这是不可能的——一旦实例化了它们,变量就有了一个特定的类型。

They are similar, though, in that constraints are implicit: only the features actually used are checked. As opposed to, say, polymorphic pointers, the actual type doesn't matter.

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

#5


3  

Yes, sort of - for example if type X has AddRef(), Release() and QueryInterface() methods with appropriate signatures it can be used as a COM object with CComPtr template class. But this is not complete duck typing - type checking is still enforced for parameters.

是的,例如,如果类型X有AddRef()、Release()和QueryInterface()方法,并具有适当的签名,它可以作为一个COM对象使用CComPtr模板类。但这并不是完全的鸭子类型检查-仍然执行参数。

#6


2  

No, this is a different concept. duck typing is a method to find out the type of a dynamic typed container. C++ templates aren't dynamic typed, they get instantiated with a specific type.

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

#7


1  

Wikipedia covers this distinction.

*这种区别。