Let's assume, that a class can use the following data-types to pass data to and from it:
std::vector<complex> // where "complex" is a struct
and
std::vector DOUBLE or INT or FLOAT or STRING
If the user passes through a std::vector<double>
this implies that a calculation has already been carried out and therefore only a small process has to be completed. If the user, however, passes through std::vector<complex>
this means that the calculation has to be carried out.
In a class I can do the following:
class Foo {
template<typename T>
Foo(T begin, T end)
{
this->transform(begin, end);
}
template<typename T>
void transform(T begin, T end)
{
std::cout << "This has been called";
}
};
But this will have to still invoke me having to have a data member
of one specific type and always assume they are doing that.
For example, is it possible to override the function transform
for 2 different cases, and, have the constructor decide which method to call depending on type of data being passed to the constructor.
It would work something like this:
int main()
{
std::vector<double> vals = {1,1,1,1,1,1,1,1};
Foo(std::begin(vals), std::end(vals)); // this will call the method that handles dbls
std::vector<complex> vals = {};
Foo(std::begin(vals), std::end(vals)); // This will call the method that handles complex numbers
}
I hope this makes sense
This can be solved through template specialization .
Considere the following function:
template<typename T>
void Foo(T arg)
{
std::cout << "General" << std::endl;
}
We can now specialize this function for char
types, this means providing another implementation for those types:
template<>
void Foo(char arg)
{
std::cout << arg << std::endl;
}
Notice that the template<>
can be omitted in this case.
If we now call our functions like this:
Foo(1);
Foo('a');
The output will be:
General
a
One way would be tag dispatching (I used struct X instead of complex
here):
#include <iostream>
#include <vector>
#include <iterator>
struct X {};
struct Foo {
template<typename T>
Foo(T begin, T end)
{
transform(begin, end, typename std::iterator_traits<T>::value_type());
}
template<typename T, typename U>
void transform(T begin, T end, U) // third parameter is unused and serves as a tag
{
std::cout << "floating point\n";
}
template<typename T>
void transform(T begin, T end, X) // same here
{
std::cout << "X\n";
}
};
int main()
{
std::vector<double> v1 = {1,1,1,1,1,1,1,1};
Foo(std::begin(v1), std::end(v1)); // floating point
std::vector<X> v2 = {};
Foo(std::begin(v2), std::end(v2)); // X
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.