C++ 模板化基类的函数模板专用化



我正在尝试为模板化类和所有派生子级实现成员函数模板专用化。它适用于班级本身,但不适用于儿童。

请看下面演示问题的示例:

#include <vector>
struct MyVector : public std::vector<int> {};
struct S {
template <typename T>
int make(T value) {
return 1;
}
template <typename T>
int make(const std::vector<T>& value) {
return 2;
}
};
int main() {
S s;
// return s.make(std::vector<int>{}); // returns 2, perfekt!
return s.make(MyVector{}); // returns 1 but should return 2
}

直播: https://godbolt.org/z/PgYkKf

我在stackoverflow上搜索了几个小时,但找不到合适的解决方案。我很感激任何提示!

函数模板专用化

第一单业务。这不是专业化。重要的是要解决这个问题以获得解决方案。这是超载。这两个函数模板重载make名称。重载分辨率在合成签名后确定哪个匹配项更好。在您的情况下,编译器可以推断出的两个签名是

int make(MyVector);
int make(std::vector<int> const&);

一个是身份转换,而另一个需要绑定对基数的引用,就转换而言,其排名比"身份"更差。因此,选择了第一个重载。

您面前有几种选择:

  1. 首选类型别名,如using MyVector = std::vector<int>;。它是向前推进的,与第二个重载完全匹配,并且由于函数模板的部分排序,它将被选中。

  2. 添加一个MyVector重载,用于委派:

    int make(MyVector const& v) { return make(static_cast<MyVector::vector const&>(v)); }
    
  3. 使用更复杂的技术来控制过载分辨率。标准库有一些用于基于 SFINAE 的过程控制的实用程序。它需要将第一个重载更改为以下内容:

    template <typename T>
    std::enable_if_t<!std::is_convertible_v<T*, std::vector<int>*>, int>
    make(T value) {
    return 1;
    }
    

    但是这种方法过于专家友好,并且很快就会无法扩展许多模板重载。我首先推荐前两种方法。

相关内容

  • 没有找到相关文章

最新更新