代码之家  ›  专栏  ›  技术社区  ›  Tristan Brindle

将模板化的基类转换运算符引入派生范围

  •  3
  • Tristan Brindle  · 技术社区  · 6 年前

    我有一个基类,它定义了一个受约束的模板化转换运算符

    struct base {
        template <typename C, std::enable_if_t<some_constraints<C>, int> = 0>
        operator C() const;
    };
    

    我还有一个派生类,它使用不同的约束实现另一个转换运算符:

    struct derived : base {
        template <typename P, std::enable_if_t<different_constraints<P>, int> = 0>
        operator P() const;
    };
    

    不幸的是,派生类中的声明隐藏了基类中的运算符。我希望将基运算符引入派生范围,但是“明显的”语法

    template <typename C>
    using base::operator C;
    

    不起作用(编译器似乎试图将其解析为别名模板声明)。

    有人知道实现这一点的正确语法吗?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Jarod42    6 年前

    我想说这是不可能的。即使是这样,派生运算符也会隐藏基运算符,因为模板参数不是根据 namespace.udecl#15.sentence-1 :

    当using声明符将基类中的声明引入派生类时,派生类中的成员函数和成员函数模板将重写和/或隐藏同名的成员函数和成员函数模板、参数类型列表、cv限定符和ref限定符(if any)在基类中(而不是冲突的)

    不幸的是,模板参数不计算,而且两个转换都不计算 operator 参数类型列表为空,为 const 没有引用限定符。

        2
  •  1
  •   Vincent Saulue-Laborde    6 年前

    下面的技巧需要GNU G++,用C++ 14。

    如果 some_constraints different_constraints 是互斥的,可以添加 using base::operator auto; 在里面 derived 类的所有转换运算符 base 可用。

    例子:

    struct Base {
    protected:
        // conversion to pointer types (protected).
        template<typename T, typename= typename std::enable_if<std::is_pointer<T>::value>::type>
        operator T() const;
    };
    
    struct Derived : public Base{
        // Make all Base conversion operators public.
        using Base::operator auto;
    
        // conversion to default constructible & non-pointer types.
        // added an extra typename=void to distinguish from Base template operator.
        template<typename T, typename= typename std::enable_if<!std::is_pointer<T>::value>::type,typename=void>
        operator T() const;
    };
    

    Live demo