Как специализировать шаблонные функции с типами шаблонов
Можно ли специализировать функцию шаблона для типов шаблонов? Я не знаю, правильна ли моя терминология, поэтому приведу простой пример того, чего я хочу достичь:
#include <vector>
#include <string>
#include <iostream>
template<typename T>
void f()
{
std::cout << "generic" << std::endl;
}
template<>
void f<std::string>()
{
std::cout << "string" << std::endl;
}
template<typename T>
void f<std::vector<T>>()
{
std::cout << "vector" << std::endl;
}
int main()
{
f<double>();
f<std::string>();
f<std::vector<int>>();
return 0;
}
Этот код не компилируется. VS2013 дает мне
ошибка C2995: 'void f(void)': шаблон функции уже определен
по этой функции:
template<typename T>
void f<std::vector<T>>()
{
std::cout << "vector" << std::endl;
}
Как я могу добиться этого поведения? Это очень важно иметь type f(void)
подпись. Является ли этот код частичной специализацией для функций (запрещено в C++)?
2 ответа
Решение
Вы не можете частично специализировать шаблонную функцию, но вы можете сделать это для класса шаблона. Таким образом, вы можете переслать вашу реализацию в выделенный класс. Может помочь следующее: ( https://ideone.com/2V39Ik)
namespace details
{
template <typename T>
struct f_caller
{
static void f() { std::cout << "generic" << std::endl; }
};
template<>
struct f_caller<std::string>
{
static void f() { std::cout << "string" << std::endl; }
};
template<typename T>
struct f_caller<std::vector<T>>
{
static void f() { std::cout << "vector" << std::endl; }
};
}
template<typename T>
void f()
{
details::f_caller<T>::f();
}
Попытка быть как можно ближе к исходному коду:
#include <vector>
#include <string>
#include <iostream>
template<typename T>
struct f {
void operator()()
{
std::cout << "generic" << std::endl;
}
};
template<>
struct f<std::string> {
void operator()()
{
std::cout << "string" << std::endl;
}
};
template<typename T>
struct f<std::vector<T> > {
void operator()()
{
std::cout << "vector" << std::endl;
}
};
int main()
{
f<double>()();
f<std::string>()();
f<std::vector<int> >()();
return 0;
}