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

问题描述 投票:0回答:1

我已将 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);
}

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

    using VectorScalarMultiplication<T, N, Vector>::operator*;
    using VectorVectorMultiplication<T, N, Vector>::operator*;
c++ templates multiple-inheritance mixins clang++
1个回答
0
投票

这是 Clang 中长期存在的 bug,其中基类中的模糊成员未被诊断出来。上面链接的错误报告中的示例使用

operator()
,但其他运算符重载也会出现错误(尽管常规命名函数被正确诊断)。该错误最近已修复。

所以你的代码本来就不应该按照它编写的方式工作,但现在它不起作用了,因为 Clang bug 已经被修复了。

© www.soinside.com 2019 - 2024. All rights reserved.