clang 18 和来自多个基础的运算符重载

Kon*_*kin 5 c++ templates multiple-inheritance mixins clang++

我已将 clang 从版本 14 升级到最新版本(主干上为 18),看来我的代码中唯一的问题是来自多个基类的运算符继承(下面是对 godbolt 的示例和引用)。这是一个简化的示例,其中我有一个最终的向量类,它派生了一些添加功能的 mixin。在这种情况下,这些混合是向量-标量乘法和向量-向量乘法,以向量点积的形式实现。两种混合都会添加,operator*但是这两个运算符都专门用于处理特定类型的类型,因此不应该有任何歧义。到目前为止,这种方法运作良好。所以我的问题是 - 这个新错误是某些标准要求的实现还是这只是编译器测试版中的一个错误而我的代码没问题?

https://godbolt.org/z/ca8Yefjdc

#include <cstddef>
#include <type_traits>
#include <array>

template<
    typename T, size_t N,
    template <typename, size_t> typename FinalTemplate
>
struct VectorData
{
    std::array<T, N> data;
};

template<
    typename T, size_t N,
    template <typename, size_t> typename FinalTemplate
>
struct VectorScalarMultiplication
{
    using Final = FinalTemplate<T, N>;

    template<typename U, typename Enable = std::enable_if_t<(
        std::is_integral_v<U> || std::is_floating_point_v<U>
    )>>
    Final operator*(const U value) const
    {
        auto copy = static_cast<const Final&>(*this);
        for (size_t i = 0; i != N; ++i)
        {
            copy.data[i] *= value;
        }

        return copy;
    }
};



template<
    typename T, size_t N,
    template <typename, size_t> typename FinalTemplate
>
struct VectorVectorMultiplication
{
    using Final = FinalTemplate<T, N>;

    T operator*(const Final& b) const
    {
        auto& a = static_cast<const Final&>(*this);
        T r{};
        for (size_t i = 0; i != N; ++i)
        {
            r += a.data[i] * b.data[i];
        }

        return r;
    }
};

template<typename T, size_t N>
struct Vector
    : public VectorData<T, N, Vector>
    , public VectorScalarMultiplication<T, N, Vector>
    , public VectorVectorMultiplication<T, N, Vector>
{
};

int main()
{
    Vector<float, 3> a;
    return static_cast<int>(a * a);
}
Run Code Online (Sandbox Code Playgroud)

如果这有帮助,将这些行添加到最终类中可以解决问题,但有点破坏 mixin 的整个想法:

    using VectorScalarMultiplication<T, N, Vector>::operator*;
    using VectorVectorMultiplication<T, N, Vector>::operator*;
Run Code Online (Sandbox Code Playgroud)

cig*_*ien 6

这是 Clang 中长期存在的错误 ,基类中的模糊成员未被诊断出来。上面链接的错误报告中的示例使用operator(),但其他运算符重载也出现错误(尽管常规命名函数被正确诊断)。该错误最近已修复。

因此,您的代码本来就不应该按其编写的方式工作,但现在由于 Clang bug 已修复,它无法工作。