Using VC++ 2010, given the following:
class Base { };
class Derived : public Base { };
template<class T> void foo(T& t); // A
void foo(Base& base); // B
Derived d;
foo(d); // calls A
foo(static_cast<Base&>(d)); // calls B
I would like "B" to be called above. I can achieve this with a cast to Base
, but why is this necessary?
I want the template function to be called for all types not derived from Base
(built-in types, etc.), but I want the non-template overload to be called for types derived from Base
, without requiring the client to explicitly cast. I also tried making the overload a specialization of the template, but the same behavior occurs in that case. What is the idiomatic way to get what I'm looking for?
the advantage of templates in a situation where you want to do the same set of operations on many different data types, is that the compiler will handle for you at compile time any possible new type you may create in the future that uses the templated function.
What is the difference between function overloading and templates? Both function overloading and templates are examples of polymorphism features of OOP. Function overloading is used when multiple functions do quite similar (not identical) operations, templates are used when multiple functions do identical operations.
Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class to work on many different data types without being rewritten for each one.
Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.
All things being equal, nontemplate functions are preferred over function templates. However, in your scenario, all things are not equal: (A) is an exact match with T = Derived
, but (B) requires a derived-to-base conversion of the argument.
You can work around this for specific cases (like this one) by using SFINAE (substitution failure is not an error) to prevent (A) from being instantiated with a type that is derived from Base
:
#include <type_traits>
#include <utility>
template <typename T>
typename std::enable_if<
!std::is_base_of<Base, T>::value
>::type foo(T& x)
{
}
void foo(Base& x)
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With