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

Ambiguous method from inheritance when using a CRTP pattern

我正在定义一个 DoubleWrapper class 继承自两个 CRTP 基础 classes,RatioableDivable,它们都定义 operator/(),签名不同:

T operator/(double const& scalar) const { return T(this->underlying().get() / scalar); }
double operator/(T const& other) const { return this->underlying().get() / other.get(); }

它们的区别在于 return 类型和参数类型。但是编译器抱怨 operator/() 是模棱两可的。请注意,构造函数是显式的,因此不存在从 double 到 DoubleWrapper 的模糊转换。

错误 C2385:'divide' 的访问不明确 注意:可能是基础 'Divable' 中的 'divide' 注意:或者可能是基础 'Ratioable'

中的 'divide'

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

测试代码:

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

源代码:

    /* Curiously Recurring Template Pattern  */
template <typename T, template<typename> class crtpType>
struct crtp
{
    T& underlying() { return static_cast<T&>(*this); }
    T const& underlying() const { return static_cast<T const&>(*this); }
};

/* Inheriting class can be divided by a scalar */
template<typename T>
struct Divable : crtp<T, Divable>
{
    T operator/(double const& scalar) const { return T(this->underlying().get() / scalar); }
};

/* Inheriting class can be divided by itself */
template<typename T>
struct Ratioable : crtp<T, Ratioable>
{
    double operator/(T const& other) const { return this->underlying().get() / other.get(); }
};

struct DoubleWrapper : 
    public Divable<DoubleWrapper>, 
    public Ratioable<DoubleWrapper>
{
    explicit DoubleWrapper(double val) : val_(val) {}

    double get() const { return val_; }

private:
    double val_;
};

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

DoubleWrapper 中没有 operator/ 所以编译器会在它的基础 类 中寻找 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