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?
问题:
回答1:
To me, C++ template used the idea of duck typing, is this right?
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.
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.
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++.
回答2:
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.
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.
回答3:
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.
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.
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.
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.
Up to you whether you define "duck typing" so that this difference means C++ doesn't have it.
回答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:
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.
回答6:
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.
回答7:
Wikipedia covers this distinction.