使用CRTP模式时继承的模糊方法

时间:2017-10-24 14:06:10

标签: c++ multiple-inheritance crtp ambiguous

我正在定义一个继承自两个CRTP基类DoubleWrapperRatioable的{​​{1}}类,它们都定义Divable,具有不同的签名:

operator/()

它们因返回类型和参数类型而异。但是编译器抱怨operator /()不明确。请注意,构造函数是显式的,因此没有从double到DoubleWrapper的模糊转换。

  • 在Visual Studio 2017上,它正在编译并运行正常但是我在代码“多个运算符”/“匹配那些操作数:( ...)”的工具提示中使用。如果我重命名运算符使其成为常规方法(T operator/(double const& scalar) const { return T(this->underlying().get() / scalar); } double operator/(T const& other) const { return this->underlying().get() / other.get(); } (...)),我收到编译错误:

错误C2385:'分歧'的模糊访问 注意:可能是基础'Divable'中的'鸿沟' 注意:或者可能是“比率”基础上的“鸿沟”

  • 即使使用运营商版本,G ++ 6.2也会给我一个编译错误:

    错误:成员'operator /'的请求不明确 double b = a / a;               ^ 注意:候选者是:double Ratioable :: operator /(const T&)const [with T = DoubleWrapper] double operator /(T const& val)const {return this-> underlying()。get()/ val.get(); }      ^ ~~~~~~~ 注意:T Divable :: operator /(const double&)const [with T = DoubleWrapper] T operator /(double const& val)const {return T(this-> underlying()。get()/ val); } ^ ~~~~~~~

C ++允许具有相同名称的方法,只要它们具有不同的签名即可。歧义来自何处?

测试代码:

divide

源代码:

    DoubleWrapper a(10.);
    double b  = a / (a/2.); // Both operator/ should be called. I would expect b value to be 2.

1 个答案:

答案 0 :(得分:1)

在重载解析之前完成名称解析。

operator/中没有DoubleWrapper,因此编译器会在其基类中查找operator/,并在两者中找到一个使名称不明确(并且不会发生重载决策)。

您可以使用using解析名称解析:

struct DoubleWrapper : 
    public Divable<DoubleWrapper>, 
    public Ratioable<DoubleWrapper>
{
    using Divable<DoubleWrapper>::operator/;
    using Ratioable<DoubleWrapper>::operator/;

    explicit DoubleWrapper(double val) : val_(val) {}

    double get() const { return val_; }

private:
    double val_;
};

有趣的阅读:

https://en.wikipedia.org/wiki/Dominance_(C++)

http://en.cppreference.com/w/cpp/language/unqualified_lookup