I have a class which acts on a list of elements, like so:
template <typename T>
class MyClass {
...
};
I need to implement certain methods, that work both on a vector<T>
and a string
- which is what most of the users would be using when they initialise an object as MyClass<char>()
.
Due to this I am being forced to follow this overloading pattern:
void method(vector<T> elements){
}
void method(string elements){
method(convertStringToVector(elements));
}
where vector<char> convertStringToVector(string str)
is defined as expected.
That is, for each class method I am being forced to add an additional method that overloads for string
. I find it an unnecessary overhead, and also sometimes forget to add it.
I will be doing exactly the same things on the string as I would do on the corresponding vector - same methods will be called in both cases, same iteration, etc. Thus, I was wondering if there is a cleaner way to do this, without adding much code overhead. Is there?
One possible way is to implement your method as a template, whose parameter is not restricted to be either string
or vector<char>
.
template <typename T>
struct MyClass
{
template <class C>
void method(C container);
};
This solves your problem because one implementation is enough for both cases:
template <typename T>
template <class C>
void MyClass<T>::method(C container)
{
std::cout << "Container has size " << container.size() << '\n';
std::cout << "First element is " << container[0] << '\n';
}
However, this will work on any container. It's not clear whether this is good (code is generic) or bad (code allows undesirable instantiations).
Imagine what happens when people try to send vector<int>
instead of vector<char>
to your method by mistake. Because you didn't build your code for this case, it will either display obscure compilation errors, or generate code which silently does the wrong thing at runtime.
You can create a class to use as parameter to your methods, which accepts both std::vector<char>
and std::string
:
class MyString
{
public:
MyString(const std::vector<char>& v) : vector(v) {}
MyString(std::vector<char>&& v) : vector(std::move(v)) {}
MyString(const std::string& s) : vector(convertStringToVector(s)) {}
std::vector<char> vector;
};
void method(MyString elements)
{
}
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