我有一个定义约束模板化转换运算符的基类
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;
};
不幸的是,派生类中的声明隐藏了基类中的运算符。我想将基本运算符引入派生范围,但是显而易见的&#34;语法
template <typename C>
using base::operator C;
不起作用(编译器似乎试图将其解析为别名模板声明)。
有没有人知道实现此目的的正确语法?
答案 0 :(得分:1)
我会说这是不可能的。即使它是,你的派生运算符也会隐藏基数,因为模板参数不属于namespace.udecl#15.sentence-1:
当using-declarator将基类的声明带入派生类时,派生类中的成员函数和成员函数模板覆盖和/或隐藏具有相同名称的成员函数和成员函数模板,parameter-type-list基类中的cv-qualification和ref-qualifier(如果有的话)(而不是冲突的)
很遗憾,模板参数不计算,且转化operator
都有空参数类型列表,const
且没有参考限定符。
答案 1 :(得分:1)
以下技巧需要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;
};
答案 2 :(得分:1)
要达到类似的效果,您可以在运算符内部移动约束,如果不满足约束,可以调用基本转换运算符:
struct base {
template <typename C, std::enable_if_t<some_constraints<C>, int> = 0>
operator C() const;
};
struct derived : base {
template <typename P>
operator P() const {
if constexpr (different_constraints<P>) {
// Overridden operator
} else {
return base::operator P();
}
}
};
或者等效地有一个常规的std::enable_if_t<different_constraints<P>, int> = 0
转换操作符和另一个std::enable_if_t<!different_constraints<P>, int> = 0
来调用基本转换操作符。
答案 3 :(得分:0)
有时您可以使用转换构造函数“解决”此问题-但这并非总是可能的(例如转换为指针T)。