模板更喜欢子类函数,而不是更专门的继承函数

罗基尔

当我使用这样的代码时,我似乎得到了意外的结果:

class Base
{
public:
    template <typename T>
    bool operator <<(int(*fx)(T)) {
        return true;
    }
};
class Sub : public Base
{
public:
    template <typename T>
    bool operator <<(T t) {
        return false;
    }
};

int foo(int a) {
    return a;
}

int main() {
    bool test = Sub() << foo;
    std::cout << "Used " << (test ? "Base" : "Sub") << " class function";
}

该代码将使用非常通用的Sub类函数,而不是GCC 4.6.3和VS C ++ v141上的专用Base类函数。

但是我希望它能做的更像是这段代码:

class AClass
{
public:
    template <typename T>
    bool operator <<(int(*fx)(T)) {
        return true;
    }
    template <typename T>
    bool operator <<(T t) {
        return false;
    }
};

int foo(int a) {
    return a;
}

int main() {
    bool test = AClass() << foo;
    std::cout << "Used " << (test ? "Specialized" : "Generic") << " class function";
}

另一方面,此代码将使用GCC 4.6.3和VS C ++ v141上预期的专用功能。

这是我的问题:

  • 这是功能还是错误?
  • 有什么好的方法可以保留多类结构,但要在它们之间选择合适的模板?
Aschepler

您看到的行为对于该示例是正确的。

当C ++遇到二进制运算符expression时A << B,它将查找三种函数和函数模板声明:

  • 通过成员名称查找表达式可以找到的功能 A.operator<<

  • 通过表达式的依赖于参数的查找将找到的函数 operator<<(A, B)

  • 一组伪声明来表示运算符的内置含义,例如 int operator<<(int, int);

通过这种方法找到的全部功能组合将在整个过载解决过程中运行,以找到最佳的过载。

您的示例中的问题在于,在第一个项目符号中,对的成员名称查找的结果Sub().operator<<仅包含中的功能模板Sub,而不包含中的其他功能模板Base这是派生类的正常“隐藏”规则:除非另有说明,否则派生类的任何成员都将隐藏所有具有相同名称的继承成员-即使该名称是像“ operator<<这样的奇特名称

解决隐藏问题的简单方法是在“取消隐藏”继承的成员中添加一个using声明

class Sub : public Base
{
public:
    template <typename T>
    bool operator <<(T t) {
        return false;
    }
    using Base::operator<<; // NOTE
};

修改的示例程序然后打印“使用的基础类的函数”,因为现在两个成员都可以用于重载可见,并且Base::operator<<模板功能更专业比Sub::operator<<模板函数。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当您在C ++中更喜欢虚拟函数而不是模板时?

我是否应该更喜欢通过嵌套的typedef或继承来调用模板元函数?

模板化类的专门继承导致成员函数返回模板化类类型,而不是继承的类类型

飞镖:更喜欢常量构造函数

大括号构造函数更喜欢使用initializer_list而不是更好的匹配。为什么?

如果我更喜欢使用raw而不是其内置函数,那么使用Knex毫无意义吗?

Java为什么更喜欢调用double构造函数?

更喜欢 lambda 而非函数对象是否明智?

为什么我更喜欢元类而不是Python中超类的继承

如何专门化模板成员函数?

模板类-成员函数专门化

专门模板函数返回向量

专门针对模板化模板参数的模板类构造函数

为什么 Clang 更喜欢主模板而不是 C++17 的专业化?

如何使编译器比Swift常规函数更喜欢我的函数?

更喜欢std :: swap而不是容器的swap()?

为什么更喜欢Typeclass而不是Inheritance?

模板函数的C ++模板子类参数

没有模板专门化的模板阶乘函数

使用部分模板类作为专门的模板函数

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

如何专门化/重载模板化类型的模板函数

模板类中的模板成员函数专门化

使用模板类专门化模板函数

如何专门化模板化的模板构造函数?

防止子类覆盖Swift中的继承函数

Java子类构造函数继承的成员

如何删除子类中的继承函数?

Groovy方法重载:方法的选择比子类更喜欢接口吗?