Reputation: 1729
I'd like to call template<typename T> foo(T x)
and manually handle these cases: T = std::vector<U>
, T = std::string
, T =
any other case.
Here's what I wrote for that:
#include <iostream>
#include <vector>
#include <string>
template<typename T> void foo_impl(const std::string &data, std::string *) {
std::cout << "foo for std::string called\n";
}
template<typename T> void foo_impl(const T &data, T *) {
std::cout << "foo for general types called\n";
}
template<typename T> void foo_impl(const std::vector<T> &data, std::vector<T> *) {
std::cout << "foo for std::vector<T> called\n";
}
template<typename T> void foo(const T &data) {
foo_impl(data, static_cast<T*>(nullptr));
}
int main() {
int i = 1;
foo(i);
std::vector<int> a = {0, 1};
foo(a);
std::string s = "abcd";
foo<std::string>(s);
return 0;
}
However, foo(std::string x)
is called as in case "T
is any other type". How do I deal with it?
Upvotes: 0
Views: 78
Reputation: 217145
For template:
template<typename T> void foo(const T &data) {
std::cout << "foo for general types called\n";
}
Following is a specialization:
template<> void foo<>(const std::string &data) {
std::cout << "foo for std::string called\n";
}
but simple overload seems more appropriate:
void foo(const std::string &data) {
std::cout << "foo for std::string called\n";
}
As partial specialization is not possible for function, you have to make a overload for vector
case:
template<typename T, typename Alloc> void foo(const std::vector<T, Alloc> &data) {
std::cout << "foo for std::vector<T, Alloc> called\n";
}
An alternative is to forward to a class/struct which can be (partially) specialized:
template <typename T>
struct foo_impl {
void operator (const T&) const
{
std::cout << "foo for general types called\n";
}
};
// specialization for std::string
template <>
struct foo_impl<std::string>
{
void operator (const T&) const
{
std::cout << "foo for std::string called\n";
}
};
// partial specialization for std::vector
template <typename T, typename A>
struct foo_impl<std::vector<T, A>>
{
void operator (const std::vector<T, A>&) const
{
std::cout << "foo for std::vector<T, A> called\n";
}
};
template <typename T>
void foo(const T& t)
{
foo_impl<T>{}(t);
}
Upvotes: 4
Reputation: 206567
It's not clear to me why you are using two layers of functions..
You can overload foo
for std::string
and std::vector<T>
.
#include <iostream>
#include <vector>
#include <string>
template<typename T> void foo(const T &data) {
std::cout << "foo for general types called\n";
}
template <typename T> void foo(const std::vector<T> &data) {
std::cout << "foo for std::vector<T> called\n";
}
void foo(const std::string &data) {
std::cout << "foo for std::string called\n";
}
int main() {
int i = 1;
foo(i);
std::vector<int> a = {0, 1};
foo(a);
std::string s = "abcd";
foo(s);
return 0;
}
Output:
foo for general types called
foo for std::vector<T> called
foo for std::string called
Upvotes: 2
Reputation: 48447
T
from template<typename T> void foo_impl(const std::string &data, std::string *)
is non-deducible (that is, it's not used in the parameter list of the function), as such, it's not considered as a viable overload.
You can remove the template<typename T>
part and make this overload a non-template:
void foo_impl(const std::string &data, std::string *) {
std::cout << "foo for std::string called\n";
}
Upvotes: 3