如何从主模板调用专用模板重载函数?

How can I call the specialized template overloaded function from the main template one?

我在模板 class 中有一个方法可以创建变量的散列。我已经将它的模板专门化为 int、double 和 std::string,就像这样

template<>
class Hash<int>
{
public:
    unsigned long operator()(const int& d) const noexcept
    {
        return d * d;
    }
};

template<>
class Hash<double>
{
public:
    unsigned long operator()(const double& d) const noexcept
    {
        long intera = floor(d);
        long frazionaria = pow(2, 24) * (d - intera);
        return intera * frazionaria;
    }
};

template<>
class Hash<std::string>
{
public:
    unsigned long operator()(const std::string& d) const noexcept
    {
        unsigned long hash = 5381;
        for (unsigned long i = 0; i << d.length(); i++)
        {
            hash = (hash << 5) + d[i];
        }
        return hash;
    }
};

然后我创建了相同方法的通用版本,它接受一个模板参数并尝试将其转换为 std::string 然后尝试在其上调用 operator() (我希望调用专业模板一)

unsigned long operator()(const Data& d) const noexcept
    {
        std::cout<<"Special hash! ";
        void *v = (void *)&d;
        size_t j = sizeof(d);
        std::string s = "";
        for (size_t k = 0; k < j; k++)
        {
            s += (((char *)v)[k]);
        }
        std::cout<<"Pre-hash: "<<s<<std::endl;
        return operator()(s);
    }

(它在 class 声明中,而其他 3 个在不同的文件中) 因此,当我在 int、double 或 std::string 上调用 Hash class 的 operator() 时,它工作正常,但是当我尝试在我的另一个 class 上调用它时,我得到此错误:

error: cannot convert ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’} to ‘const lasd::BST<int>&’
   35 |                         return operator()(s);
      |                                           ^
      |                                           |
      |                                           std::string {aka std::__cxx11::basic_string<char>}

所以在我看来它正在尝试再次调用 operator(BST),即使我已经向它传递了一个字符串。有什么办法可以解决这个问题吗?我不关心散列函数不正确,我有一个 uni 分配来这样做,我只需要了解是否有可能从普通模板调用专门的模板函数。 我也试过使用

return operator()<std::string>(s);

正如我在类似问题的其他一些答案中看到的那样,但我收到以下错误:

error: expected primary-expression before ‘>’ token
   35 |                         return operator()<std::string>(s);
      |                                                      ^

https://gcc.godbolt.org/z/9oz8Gf9aM

如果我没理解错的话,你的 operator() 需要一个 Hash 实例来调用它的专用 operator()

auto operator()(const Data& d) const noexcept
{
    // ....
    std::string s = "";
    return Hash<std::string>{}.operator()(s);
    //     ^^^^^^^^^^^^^^^^^^^ 
    // OR simply
    // return Hash<std::string>{}(s);
  
}

更新

根据更新后的 post/ 错误消息,您正在使用尚未声明和定义的特化 Hash<std::string>。那是在行:

return Hash<std::string>{}(s);

编译器不知道 std::stringHash 专业化。因此,错误!

(一种方法)修复它,你需要拆分声明和定义如下:

template<typename Data> class Hash
{
public:
    // declare the operator()
    auto operator()(const Data& d) const noexcept;
};
template<> class Hash<int> { /* ...code... */ };
template<> class Hash<double> { /* ...code... */ };
template<> class Hash<std::string> { /* ...code... */ };

// define the operator()
template<typename Data>
auto Hash<Data>::operator()(const Data& d) const noexcept
{
    // code!
    return Hash<std::string>{}(s);
}

See a demo