I have the following problem:
class Base
{
};
class Derived : public Base
{
};
class Different
{
};
class X
{
public:
template <typename T>
static const char *func(T *data)
{
// Do something generic...
return "Generic";
}
static const char *func(Base *data)
{
// Do something specific...
return "Specific";
}
};
If I now do
Derived derived;
Different different;
std::cout << "Derived: " << X::func(&derived) << std::endl;
std::cout << "Different: " << X::func(&different) << std::endl;
I get
Derived: Generic
Different: Generic
But what I want is that for all classes derived from Base the specific method is called. So the result should be:
Derived: Specific
Different: Generic
Is there any way I can redesign the X:func(...)s to reach this goal?
EDIT:
Assume that it is not known by the caller of X::func(...) if the class submitted as the parameter is derived from Base or not. So Casting to Base is not an option. In fact the idea behind the whole thing is that X::func(...) should 'detect' if the parameter is derived from Base or not and call different code. And for performance reasons the 'detection' should be made at compile time.
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
Explanation: As a template feature allows you to write generic programs. therefore a template function works with any type of data whereas normal function works with the specific types mentioned while writing a program.
@kushal Yes but with template, the compiler create a new function for every type used, while with function overloading you keep control of how many function exist in the final program. Template makes the program bigger.
Function overloading is used when multiple functions do similar operations; templates are used when multiple functions do identical operations. Templates provide an advantage when you want to perform the same action on types that can be different.
I found a VERY easy solution!
class Base
{
};
class Derived : public Base
{
};
class Different
{
};
class X
{
private:
template <typename T>
static const char *intFunc(const void *, T *data)
{
// Do something generic...
return "Generic";
}
template <typename T>
static const char *intFunc(const Base *, T *data)
{
// Do something specific...
return "Specific";
}
public:
template <typename T>
static const char *func(T *data)
{
return intFunc(data, data);
}
};
This works great and is very slim! The trick is to let the compiler select the correct method by the (otherwise useless) first parameter.
You must use SFINAE for this. In the following code, the first function can be instantiated if and only if you pass something that can't be (implicitly) converted to Base *
. The second function has this reversed.
You might want to read up on enable_if
.
#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
class Base {};
class Derived : public Base {};
class Different {};
struct X
{
template <typename T>
static typename boost::disable_if<boost::is_convertible<T *, Base *>,
const char *>::type func(T *data)
{
return "Generic";
}
template <typename T>
static typename boost::enable_if<boost::is_convertible<T *, Base *>,
const char *>::type func(T *data)
{
return "Specific";
}
};
int main()
{
Derived derived;
Different different;
std::cout << "Derived: " << X::func(&derived) << std::endl;
std::cout << "Different: " << X::func(&different) << std::endl;
}
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