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

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?

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.

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.

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++.

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.

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.

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.

Wikipedia covers this distinction.

Related

How to know the required interface/contract of template arguments in C++?

Sorry for the newbie question, but I have a feeling I am missing something here:
If I have a certain class template which looks like this (basically the only way to pass a lambda to a function in C++, unless I am mistaken):
template<typename V, typename F>
class Something
{
public:
int some_method(V val, F func) {
double intermediate = val.do_something();
return func(intermediate);
}
}
By reading the implementation of this class, I can see that the V class must implement double do_something(), and that F must be a function/functor with the signature int F(double).
However, in languages like Java or C#, the constraints for the generic parameters are explicitly stated in the generic class signature, so they are obvious without having to look at the source code, e.g.
class Something<V> where V : IDoesSomething // interface with the DoSomething() method
{
// func delegate signature is explicit
public int SomeMethod(V val, Func<double, int> func)
{
double intermediate = val.DoSomething();
return func(intermediate);
}
}
My question is: how do I know how to implement more complex input arguments in practice? Can this somehow be documented using code only, when writing a library with template classes in C++, or is the only way to parse the code manually and look for parameter usage?
(or third possibility, add methods to the class until the compiler stops failing)
C# and Java Generics have similar syntax and some common uses with C++ templates, but they are very different beasts.
Here is a good overview.
In C++, by default template checking was done by instantiation of code, and requrements are in documentation.
Note that much of the requirements of C++ templates is semantic not syntactic; iterators need not only have the proper operations, those operations need to have the proper meaning.
You can check syntactic properties of types in C++ templates. Off the top of my head, there are 6 basic ways.
You can have a traits class requirement, like std::iterator_traits.
You can do SFINAE, an accidentally Turing-complete template metaprogramming technique.
You can use concepts and/or requires clauses if your compiler is modern enough.
You can generate static_asserts to check properties
You can use traits ADL functions, like begin.
You can just duck type, and use it as if it had the properties you want. If it quacks like a duck, it is a duck.
All of these have pluses and minuses.
The downside to all of them is that they can be harder to set up than "this parameter must inherit from the type Foo". Concepts can handle that, only a bit more verbose than Java.
Java style type erasure can be dominated using C++ templates. std::function is an example of a duck typed type eraser that allows unrelated types to be stored as values; doing something as restricted as Java is rarely worthwhile, as the machinery to do it is harder than making something more powerful.
C# reification cannot be fully duplicated by C++, because C#'s runtime environment ships with a compiler, and can effectively compile a new type when you instantiate at runtime. I have seen people ship compilers with C++ programs, compile dynamic libraries, then load and execute them, but that isn't something I'd advise.
Using modern c++20, you can:
template<Number N>
struct Polynomial;
where Number is a concept which checks N (a type) against its properties. This is a bit like the Java signature stuff on steroids.
And by c++23 you'll be able to use compile time reflection to do things that make templates look like preprocessor macros.

C++: are "trait" and "meta-function" synonymous?

Or, does trait perhaps refer to a specific way to utilizing meta-functions?
If they are not synonymous, please point me to some examples of traits which are not meta-functions or those of meta-functions which are not traits. An actually working piece of code, perhaps within STL or Boost libraries, would be appreciated rather than a contrived toy example.
I'd like to see how experts in this field of C++ programming use these terminologies. I'm not sure if there are authoritative definitions of them...
Thanks in advance!
Clarification: It's not that I looking for any examples of traits or meta-functions. I've been using tens (if not hundreds) of them at my day job.
"Venn0110". Licensed under Public Domain via Commons.
"Meta" is C++ terminology for template programming. A clear example is the Boost Meta Programming Library (MPL).
In this sense, a meta-function is a function whose domain is not objects but C++ constructs. The common inputs are therefore types, ordinary functions and other templates.
A simple meta-function is for example template<typename T> using Foo = Bar<T, int> which has as its input a type T and as its output a type Foo<T>. Trivial, yes, but ordinary functions can be trivial too.
A trait is a metafunction whose codomain is a constant expression, often boolean. E.g. is_foo<T>::value obviously is boolean. The oldest trait in this sense is sizeof(T) whose codomain is size_t.
The terms are not equivalent.
Meta functions
The term is not defined in the C++ Standard.
There seem to be two main contending definitions:
1) "meta-functions derive/calculate/map-to values or types (based on their arguments/parameters) at compile time", and/or
constexpr functions may or may not be included in any given person's definition/conception; there's functional overlap, but much existing writing mentioning meta functions predates or just doesn't also discuss constexpr functions, so it's hard to know whether any definition or examples given deliberately leaves room for or excludes them
2) "meta-functions are functions and/or classes utilising template meta-programming", which specifically means a core of code (the template) may be reused for different parameters, performing some code generation or transformation based thereon
it's not necessarily the case that a meta-programming's final product is a compile-time type or constant - it may be a function intended for use with runtime values or data
A small survey of top google results for "meta function c++"
"metafunctions accept types and compile-time constants as parameters and return types/constants. A metafunction, contrary to its name, is a class template."
"code...executed and its result used while...compiling. ...meta-functions can compute two things: values or types"
this article uses "meta function" to refer to class templates yielding compile-time values/types
Traits
The C++ Standard doesn't define "traits", but does define "traits class"es:
17.3.25 [defns.traits] traits class
a class that encapsulates a set of types and functions necessary for class templates and function templates to manipulate objects of types for which they are instantiated
[ Note: Traits classes defined in Clauses 21, 22 and 27 are character traits, which provide the character handling support needed by the string and iostream classes. —end note ]
I'd add that traits can have values, as well as types and functions - for example rank exposes ::value. Traits provide types/values offering insight into either the parameter type itself, or the behaviour desired of the system using the trait when that system's working on variables of that type.
The Standard Library's character traits contain example of runtime functionality: for example X::length(p), X::find(p, n, c).
The <type_traits> header in the C++ Standard Library is a good place to get an initial feel for what kind of things traits can be used for.
Traits are traditionally and typically (but now C++11 provides constexpr functions not necessarily) classes, as distinct from functions meta- or otherwise.
A trait might tell you if a parameter T is constant or not, whether it's serialisable, or whether it should be compressed when transmitted via TCP: whatever some other general-purpose code might need to customise its behaviour for the range of types it handles.
Sometimes traits will be provided by the system that uses them - other times they can be supplied by client code wishing to customise its behaviour on a per-type basis.
Traits may deduce things using various tests of the parameter types, or they may be hand-crafted specialisations hard-coding values for specific types.
This ACCU introduction to traits](http://accu.org/index.php/journals/442) is worth reading, and includes this quote from the creator of C++:
Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine "policy" or "implementation details". - Bjarne Stroustrup
Contrasting "meta function" with "traits"
Regardless of which definition of meta function you adopt, the criteria relates to implementation details: when the function can be evaluated, and/or whether it involves code generation/transformation. That contrasts with traits, where the key concept/requirement is the purpose to which they're put, not the common - but far from universal - implementation using template specialisations or instantiations, or any capacity for compile time vs run-time evaluation.
A metafunction (in the context of C++) is a function that produces a result that can be used at compile time. The result can either be types (which can only be obtained at compile time by definition, using techniques such as partial specialisation) or values (which can be computed at compile time, using the fact that template parameters can be integral values, not just types).
A trait is essentially a class (or object) that packages up information (policy contraints, type characteristics, implementation details) for use by another class (or object) at compile time. The information packaged up can consist of type information (e.g. typedefs) or properties of interest. For example, std::numeric_limits<T> (available through <limits>) is a "type trait" which provides information about arithmetic types (e.g. is T an integral type? is the set of values a T can represent bounded or finite? is T signed? etc). The information is packaged in a form so that metaprograms (i.e. template functions or classes) can use the information at compile time. For example, a template metafunction might use information from a type trait to ensure the template is only instantiated for unsigned integral types, and trigger a compilation error if an attempt is made to instantiate the template for other types.
In this sense, a trait is a type of metafunction that provides information at compile time for use by other metafunctions.
As far as I know, there aren't any formal definitions of these terms. So I'll provide the ones that I use.
Metafunctions are templates which return a type. Usually, the returned result is a type which contains a member type named "type" so it can be accessed via the suffix ::type. Example invoking a metafunction:
using new_type = std::common_type<int, char>::type;
(see http://en.cppreference.com/w/cpp/types/common_type)
A trait would be be special type of metafunction which returns a result convertible to bool. Example:
bool ic = std::is_convertible<char, int>::type;
Note that nowadays, the requirement that a metafunction result have a member name "type" is relaxed so some metafunctions might be defined in such a manner that the ::type can be dropped. Example:
bool ic = std::experimental::is_convertible_v<char, int>;

Why is it bad to impose type constraints on templates in C++?

In this question the OP asked about limiting what classes a template will accept. A summary of the sentiment that followed is that the equivalent facility in Java is bad; and don't do this.
I don't understand why this is bad. Duck typing is certainly a powerful tool; but in my mind it lends itself confusing runtime issues when a class looks close (same function names) but has slightly different behavior. And you can't necessarily rely on compile time checking because of examples like this:
struct One { int a; int b };
struct Two { int a; };
template <class T>
class Worker{
T data;
void print() { cout << data.a << endl; }
template <class X>
void usually_important () { int a = data.a; int b = data.b; }
}
int main() {
Worker<Two> w;
w.print();
}
Type Two will allow Worker to compile only if usually_important is not called. This could lead to some instantiations of Worker compiling and others not even in the same program.
In a case like this, though. The responsibility is put on to the designer of ENGINE to ensure that it is a valid type (after which they should inherit ENGINE_BASE). If they don't, there will be a compiler error. To me this seems much safer while not imposing any restrictions or adding much additional work.
class ENGINE_BASE {}; // Empty class, all engines should extend this
template <class ENGINE>
class NeedsAnEngine {
BOOST_STATIC_ASSERT((is_base_of<ENGINE_BASE, ENGINE>));
// Do stuff with ENGINE...
};
This is too long, but it might be informative.
Generics in Java are a type erasure mechanism, and automatic code generation of type casts and type checks.
templates in C++ are code generation and pattern matching mechanisms.
You can use C++ templates to do what Java generics do with a bit of effort. std::function< A(B) > behaves in a covariant/contravariant fashion with regards to A and B types and conversion to other std::function< X(Y) >.
But the primary design of the two is not the same.
A Java List<X> will be a List<Object> with some thin wrapping on it so users don't have to do type casts on extraction. If you pass it as a List<? extends Bar>, it again is getting a List<Object> in essence, it just has some extra type information that changes how the casts work and which methods can be invoked. This means you can extract elements from the List into a Bar and know it works (and check it). Only one method is generated for all List<? extends Bar>.
A C++ std::vector<X> is not in essence a std::vector<Object> or std::vector<void*> or anything else. Each instance of a C++ template is an unrelated type (except template pattern matching). In fact, std::vector<bool> uses a completely different implementation than any other std::vector (this is now considered a mistake because the implementation differences "leak" in annoying ways in this case). Each method and function is generated independently for the particular type you pass it.
In Java, it is assumed that all objects will fit into some hierarchy. In C++, that is sometimes useful, but it has been discovered it is often ill fitting to a problem.
A C++ container need not inherit from a common interface. A std::list<int> and std::vector<int> are unrelated types, but you can act on them uniformly -- they both are sequential containers.
The question "is the argument a sequential container" is a good question. This allows anyone to implement a sequential container, and such sequential containers can as high performance as hand-crafted C code with utterly different implementations.
If you created a common root std::container<T> which all containers inherited from, it would either be full of virtual table cruft or it would be useless other than as a tag type. As a tag type, it would intrusively inject itself into all non-std containers, requiring that they inherit from std::container<T> to be a real container.
The traits approach instead means that there are specifications as to what a container (sequential, associative, etc) is. You can test these specifications at compile time, and/or allow types to note that they qualify for certain axioms via traits of some kind.
The C++03/11 standard library does this with iterators. std::iterator_traits<T> is a traits class that exposes iterator information about an arbitrary type T. Someone completely unconnected to the standard library can write their own iterator, and use std::iterator<...> to auto-work with std::iterator_traits, add their own type aliases manually, or specialize std::iterator_traits to pass on the information required.
C++11 goes a step further. for( auto&& x : y ) can work with things that where written long before the range-based iteration was designed, without touching the class itself. You simply write a free begin and end function in the namespace that the class belongs to that returns a valid forward iterator (note: even invalid forward iterators that are close enough work), and suddenly for ( auto&& x : y ) starts working.
std::function< A(B) > is an example of using these techniques together with type erasure. It has a constructor that accepts anything that can be copied, destroyed, invoked with (B) and whose return type can be converted to A. The types it can take can be completely unrelated -- only that which is required is tested for.
Because of std::functions design, we can have lambda invokables that are unrelated types that can be type-erased into a common std::function if needed, but when not type erased their invokation action is known from there type. So a template function that takes a lambda knows at the point of invokation what will happen, which makes inlining an easy local operation.
This technique is not new -- it was in C++ since std::sort, a high level algorithm that is faster than C's qsort due to the ease of inlining invokable objects passed as comparators.
In short, if you need a common runtime type, type erase. If you need certain properties, test for those properties, don't force a common base. If you need certain axioms to hold (untestable properties), either document or require callers to claim those properties via tags or traits classes (see how the standard library handles iterator categories -- again, not inheritance). When in doubt, use free functions with ADL enabled to access properties of your arguments, and have your default free functions use SFINAE to look for a method and invoke if it exists, and fail otherwise.
Such a mechanism removes the central responsibility of a common base class, allows existing classes to be adapted without modification to pass your requirements (if reasonable), places type erasure only where it is needed, avoids virtual overhead, and ideally generates clear errors when properties are found to not hold.
If your ENGINE has certain properites it needs to pass, write a traits class that tests for those.
If there are properties that cannot be tested for, create tags that describe such properties. Use specialization of a traits class, or canonical typedefs, to let the class describe which axioms hold for the type. (See iterator tags).
If you have a type like ENGINE_BASE, don't demand it, but instead use it as a helper for said tags and traits and axiom typedefs, like std::iterator<...> (you never have to inherit from it, it simply acts as a helper).
Avoid over specifying requirements. If usually_important is never invoked on your Worker<X>, probably your X doesn't need a b in that context. But do test for properties in a way clearer than "method does not compile".
And sometimes, just punt. Following such practices might make things harder for you -- so do an easier way. Most code is written and discarded. Know when your code will persist, and write it better and more extendably and more maintainably. Know that you need to practice those techniques on disposable code so you can write it correctly when you have to.
Let me turn the question around on you: Why is it bad that the code compiles for Two if usually_important isn't called? The type you gave it meets all the needs for that particular instantiation and the compiler will immediately tell you if a particular instantiation no longer meets the interface needed for the needed functionality in the template.
That said if you insist that you need an Engine object, don't do it with templates at all, instead treat it as a sort of strategy pattern with a non-template (using this approach enforces at compile time that the user-defined type adheres to a specific interface, not just that it looks like a duck):
class Worker
{
public:
explicit Worker(EngineBase* data) : data_(data) {}
void print() { cout << data_->a() << endl; }
template <class X>
void usually_important () { int a = data_->a(); int b = data_->b(); }
private:
EngineBase* data_;
}
int main()
{
Worker w(new ConcreteEngine);
w.print();
}
I don't understand why this is bad. Duck typing is certainly a
powerful tool; but in my mind it lends itself confusing runtime issues
when a class looks close (same function names) but has slightly
different behavior.
The probability that you can define a non-trivial interface and then by accident have another interface that has different semantics but can be substituted is minimal. This never, ever happens.
Type Two will allow Worker to compile only if usually_important is not
called.
That is a good thing. We depend on it all the time. It makes class templates more flexible.
Matching a compile-time interface is strictly superior to a run-time one. This is because run-time interfaces can't differ in key ways that compile-time ones can (e.g. different types in the interface), and require a bunch of run-time abstraction like dynamic allocation that may be unnecessary.
In a case like this, though. The responsibility is put on to the
designer of ENGINE to ensure that it is a valid type (after which they
should inherit ENGINE_BASE). If they don't, there will be a compiler
error. To me this seems much safer while not imposing any restrictions
or adding much additional work.
It is not safer. It is utterly pointless. It is stupendously unlikely that the user will accidentally instantiate the class with the wrong type but it will compile successfully due to circumstantial interface match.
What it really boils down to is this: you should only require what you really need. Absolutely definitely must have in order to function. Everything else, don't require it. This is a core tenet of making software maintainable. You cannot possibly imagine what shenanigans I might conceive of long after you have written this class to use it in ways that you never thought it could be used for.

Enforce functions to implement for template argument class?

Should I define an interface which explicitly informs the user what all he/she should implement in order to use the class as template argument or let the compiler warn him when the functionality is not implemented ?
template <Class C1, Class C2>
SomeClass
{
...
}
Class C1 has to implement certain methods and operators, compiler won't warn until they are used. Should I rely on compiler to warn or make sure that I do:
Class C1 : public SomeInterfaceEnforcedFunctions
{
// Class C1 has to implement them either way
// but this is explicit? am I right or being
// redundant ?
}
Ideally, you should use a concept to specify the requirements on the type used as a template argument. Unfortunately, neither the current nor the upcoming standard includes concepts.
Absent that, there are various methods available for enforcing such requirements. You might want to read Eric Neibler's article about how to enforce requirements on template arguments.
I'd agree with Eric's assertion that leaving it all to the compiler is generally unacceptable. It's much of the source of the horrible error messages most of us associate with templates, where seemingly trivial typos can result in pages of unreadable dreck.
If you are going to force an interface, then why use a template at all? You can simply do -
class SomeInterface //make this an interface by having pure virtual functions
{
public:
RType SomeFunction(Param1 p1, Param2 p2) = 0;
/*You don't have to know how this method is implemented,
but now you can guarantee that whoever wants to create a type
that is SomeInterface will have to implement SomeFunction in
their derived class.
*/
};
followed by
template <class C2>
class SomeClass
{
//use SomeInterface here directly.
};
Update -
A fundamental problem with this approach is that it only works for types that is rolled out by a user. If there is a standard library type that conforms to your interface specification, or a third party code or another library (like boost) that has classes that conform to SomeInterface, they won't work unless you wrap them in your own class, implement the interface and forward the calls appropriately. I'm somehow not liking my answer anymore.
Absent of concepts, a for now abandoned concept (pun not intended, but noted) for describing which requirements a template parameter must fulfill, the requirements are only enforced implicitly. That is, if whatever your users use as a template parameter doesn't fulfill them, the code won't compile. Unfortunately, the error message resulting from that are often quite gibberish. The only things you can do to improve matters is to
describe the requirements in your template's documentation
insert code that checks for those requirements early on in your template, before it delves so deep that the error messages your users get become unintelligibly.
The latter can be quite complicated (static_assert to the rescue!) or even impossible, which is the reason concepts where considered to become a core-language feature, instead of a library.
Note that it is easy to overlook a requirement this way, which will only become apparent when someone uses a type as a template parameter that won't work. However, it is at least as easy to overlook that requirements are often quite lose and put more into the description than what the code actually calls for.
For example, + is defined not only for numbers, but also for std::string and for any number of user-defined types. Conesequently, a template add<T> might not only be used with numbers, but also with strings and an infinite number of user-defined types. Whether this is an unwanted side-effect of the code you want to suppress or a feature you want to support is up to you. All I'm saying is that it is not easy to catch this.
I don't think defining an interface in the form of an abstract base class with virtual functions is a good idea. This is run-time polymorphism, a main pillar classic OO. If you do this, then you don't need a template, just take the base class per reference.
But then you also lose one of the main advantages of templates, which is that they are, in some ways, more flexible (try to write an add() function classic OO which works with any type overloading + in) and faster, because the binding of the function calls take place not at run-time, but during compilation. (That brings more than it might look like at first due to the ability to inline, which usually isn't possible with run-time polymorphism.)

compile time polymorphism and runtime polymorphism

I noticed that somewhere polymorphism just refer to virtual function. However, somewhere they include the function overloading and template. Later, I found there are two terms, compile time polymorphism and run-time polymorphism. Is that true?
My question is when we talked about polymorphism generally, what's the widely accepted meaning?
Yes, you're right, in C++ there are two recognized "types" of polymorphism. And they mean pretty much what you think they mean
Dynamic polymorphism
is what C#/Java/OOP people typically refer to simply as "polymorphism". It is essentially subclassing, either deriving from a base class and overriding one or more virtual functions, or implementing an interface. (which in C++ is done by overriding the virtual functions belonging to the abstract base class)
Static polymorphism
takes place at compile-time, and could be considered a variation of ducktyping. The idea here is simply that different types can be used in a function to represent the same concept, despite being completely unrelated. For a very simple example, consider this
template <typename T>
T add(const T& lhs, const T& rhs) { return lhs + rhs; }
If this had been dynamic polymorphism, then we would define the add function to take some kind of "IAddable" object as its arguments. Any object that implement that interface (or derive from that base class) can be used despite their different implementations, which gives us the polymorphic behavior. We don't care which type is passed to us, as long as it implements some kind of "can be added together" interface.
However, the compiler doesn't actually know which type is passed to the function. The exact type is only known at runtime, hence this is dynamic polymorphism.
Here, though, we don't require you to derive from anything, the type T just has to define the + operator. It is then inserted statically. So at compile-time, we can switch between any valid type as long as they behave the same (meaning that they define the members we need)
This is another form of polymorphism. In principle, the effect is the same: The function works with any implementation of the concept we're interested in. We don't care if the object we work on is a string, an int, a float or a complex number, as long as it implements the "can be added together" concept.
Since the type used is known statically (at compile-time), this is known as static polymorphism. And the way static polymorphism is achieved is through templates and function overloading.
However, when a C++ programmer just say polymorphism, they generally refer to dynamic/runtime polymorphism.
(Note that this isn't necessarily true for all languages. A functional programmer will typically mean something like static polymorphism when he uses the term -- the ability to define generic functions using some kind of parametrized types, similar to templates)
"Polymorphism" literally means "many forms". The term is unfortunately a bit overloaded in computer science (excuse the pun).
According to FOLDOC, polymorphism is "a concept first identified by Christopher Strachey (1967) and developed by Hindley and Milner, allowing types such as list of anything."
In general, it's "a programming language feature that allows values of different data types to be handled using a uniform interface", to quote Wikipedia, which goes on to describe two main types of polymorphism:
Parametric polymorphism is when the same code can be applied to multiple data types. Most people in the object-oriented programming community refer to this as "generic programming" rather than polymorphism. Generics (and to some extent templates) fit into this category.
Ad-hoc polymorphism is when different code is used for different data-types. Overloading falls into this category, as does overriding. This is what people in the object-oriented community are generally referring to when they say "polymorphism". (and in fact, many mean overriding, not overloading, when they use the term "polymorphism")
For ad-hoc polymorphism there's also the question of whether the resolution of implementation code happens at run-time (dynamic) or compile-time (static). Method overloading is generally static, and method overriding is dynamic. This is where the terms static/compile-time polymorphism and dynamic/run-time polymorphism come from.
Usually people are referring to run-time polymorpism in my experience ...
When a C++ programmer says "polymorphism" he most likely means subtype polymorphism, which means "late binding" or "dynamic binding" with virtual functions. Function overloading and generic programming are both instances of polymorphism and they do involve static binding at compile time, so they can be referred to collectively as compile-time polymorphism. Subtype polymorphism is almost always referred to as just polymorphism, but the term could also refer to all of the above.
In its most succinct form, polymorphism means the ability of one type to appear as if it is another type.
There are two main types of polymorphism.
Subtype polymorphism: if D derives from B then D is a B.
Interface polymorphism: if C implements an interface I.
The first is what you are thinking of as runtime polymorphism. The second does not really apply to C++ and is a really a concept that applies to Java and C#.
Some people do think of overloading in the special case of operators (+, -, /, *) as a type of polymorphism because it allows you to think of types that have overloaded these operators as replaceable for each other (i.e., + for string and + for int). This concept of polymorphism most often applies to dynamic languages. I consider this an abuse of the terminology.
As for template programming, you will see some use the term "polymorphism" but this is really a very different thing than what we usually mean by polymorphism. A better name for this concept is "generic programming" or "genericity."
Various types of Function overloading (compile time polymorphism ...
9 Jun 2011 ... Polymorphism means same entity behaving differently at different times. Compile time polymorphism is also called as static binding.
http://churmura.com/technology/programming/various-types-of-function-overloading-compile-time-polymorphism-static-binding/39886/
A simple explanation on compile time polymorphism and run time polymorphism from :
questionscompiled.com
Compile time Polymorphism:
C++ support polymorphism. One function multiple purpose, or in short many functions having same name but with different function body.
For every function call compiler binds the call to one function definition at compile time. This decision of binding among several functions is taken by considering formal arguments of the function, their data type and their sequence.
Run time polymorphism:
C++ allows binding to be delayed till run time. When you have a function with same name, equal number of arguments and same data type in same sequence in base class as well derived class and a function call of form: base_class_type_ptr->member_function(args); will always call base class member function. The keyword virtual on a member function in base class indicates to the compiler to delay the binding till run time.
Every class with atleast one virtual function has a vtable that helps in binding at run time. Looking at the content of base class type pointer it will correctly call the member function of one of possible derived / base class member function.
Yes, you are basically right. Compile-time polymorphism is the use of templates (instances of which's types vary, but are fixed at compile time) whereas run-time polymorphism refers to the use of inheritance and virtual functions (instances of which's types vary and are fixed at run time).