模板重载解决问题

template overload resolution trouble

鉴于此代码:

#include <string>
#include <vector>
#include <iostream>

template <typename T>
std::string stringify(const T&) {
    return "{?}";
}

template <typename T>
std::string proxy(const T& in) {
    return stringify(in);
}

// trying to specialize "stringify()"

template <typename T>
std::string stringify(const std::vector<T>& in) {
    return "vector specialization!";
}

template <>
std::string stringify(const std::vector<int>& in) {
    return "INT vector specialization!";
}

int main() {
    std::cout << proxy(1); // calls the 1st

    std::vector<int> intVec;
    std::cout << proxy(intVec); // calls the 1st

    std::vector<double> dblVec;
    std::cout << proxy(dblVec); // calls the 1st

    return 0;
}

如何在 proxy<> 之后将 stringify() 专门化为 vector<>

目前我得到{?}{?}{?}

如果我删除这个 - stringify(const std::vector<T>& in) 然后 vector<int> 开始被调用,因为它将是第一个的专业化。

然后我会得到{?}INT vector specialization!{?}

有没有办法从 proxy() 调用任何 2 个向量专业化字符串化函数 - 如果它们是最后定义的 - 在 proxy() 函数之后?

有没有一种方法可以部分专注于 vector<> 并且仍然可以从 proxy<> 调用?

我不想专攻 vector<int>vector<double>vector<UserType>...

编辑: 忘了说我需要这个 C++98

首先,避免特化函数模板,更喜欢重载。请参阅 Herb Sutter's article 了解潜在的陷阱。

其次,您 运行 遇到的问题涉及函数模板中从属名称的名称查找工作方式。在 proxy<T> 中,stringify 是一个从属名称 - 它取决于 T。该名称将在模板的定义点(将找到 stringify<T>(const T&) 而不是其他重载)和在参数的关联命名空间中的实例化点再次查找(这将是 std).这些查找都没有找到您的其他功能。

我们可以利用查找的第二部分——参数相关查找。让我们将所有内容都放在一个命名空间中(我将其命名为 N 是任意的,请根据需要随意重命名):

namespace N {
    struct helper { };

    template <typename T>
    std::string stringify(helper, const T&) {
        return "{?}";
    }
}

template <typename T>
std::string proxy(const T& in) {
    return stringify(N::helper(), in);
}

好的,到目前为止我们完全没有改变任何东西。在所有情况下,我们仍然得到 {?}。但是现在我们可以进一步 overloads (不是特化) stringify 仍然在那个命名空间中但是在 proxy:

的定义之后
namespace N {    
    template <typename T>
    std::string stringify(helper, const std::vector<T>& ) {
        return "vector overload!";
    }

    std::string stringify(helper, const std::vector<int>& ) {
        return "INT vector overload!";
    }
}

这两个重载将在名称查找的第二阶段找到,因为 Nhelper 的关联命名空间。现在 proxy(intVFec) 将找到 stringify 的所有三个重载,而不仅仅是一个。现在您的代码打印:

{?}INT vector overload!vector overload!

随心所欲。 None 以上需要 C++11。