模板专门化问题

Template specialisation issue

本文关键字:问题 专门化      更新时间:2023-10-16

我想调用template<typename T> foo(T x)并手动处理这些情况:T = std::vector<U>, T = std::string, T =任何其他情况

我是这么写的:

#include <iostream>
#include <vector>
#include <string>
template<typename T> void foo_impl(const std::string &data, std::string *) {
  std::cout << "foo for std::string calledn";
}
template<typename T> void foo_impl(const T &data, T *) {
  std::cout << "foo for general types calledn";
}
template<typename T> void foo_impl(const std::vector<T> &data, std::vector<T> *) {
  std::cout << "foo for std::vector<T> calledn";
}
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;
}

然而,foo(std::string x)被调用,以防"T是任何其他类型"。我该怎么处理呢?

For template:

template<typename T> void foo(const T &data) {
  std::cout << "foo for general types calledn";
}

下面是一个专门化:

template<> void foo<>(const std::string &data) {
    std::cout << "foo for std::string calledn";
}

,但简单的重载似乎更合适:

void foo(const std::string &data) {
    std::cout << "foo for std::string calledn";
}

由于不可能对函数进行部分专门化,因此必须对vector情况进行重载:

template<typename T, typename Alloc> void foo(const std::vector<T, Alloc> &data) {
  std::cout << "foo for std::vector<T, Alloc> calledn";
}

另一种方法是转发到可以(部分)专门化的类/结构:

template <typename T>
struct foo_impl {
    void operator (const T&) const
    {
        std::cout << "foo for general types calledn";
    }
};
// specialization for std::string
template <>
struct foo_impl<std::string>
{
    void operator (const T&) const
    {
        std::cout << "foo for std::string calledn";
    }
};
// 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> calledn";
    }
};
template <typename T>
void foo(const T& t)
{
    foo_impl<T>{}(t);
}

来自template<typename T> void foo_impl(const std::string &data, std::string *)T是不可演绎的(也就是说,它没有在函数的参数列表中使用),因此,它不被认为是可行的重载。

您可以删除template<typename T>部分,并使此重载为非模板:

void foo_impl(const std::string &data, std::string *) {
  std::cout << "foo for std::string calledn";
}

我不清楚你为什么要使用两层函数…

可以为std::stringstd::vector<T>重载foo

#include <iostream>
#include <vector>
#include <string>
template<typename T> void foo(const T &data) {
  std::cout << "foo for general types calledn";
}
template <typename T> void foo(const std::vector<T> &data) {
  std::cout << "foo for std::vector<T> calledn";
}
void foo(const std::string &data) {
  std::cout << "foo for std::string calledn";
}
int main() {
  int i = 1;
  foo(i);
  std::vector<int> a = {0, 1};
  foo(a);
  std::string s = "abcd";
  foo(s);
  return 0;
}
输出:

foo for general types called
foo for std::vector<T> called
foo for std::string called