编译在我的 Mac 上工作,但在集群上不工作 (Linux)

Compilation working on my Mac but not on the cluster (Linux)

我有一个 c++17 的库,它在我的 Mac 上编译,但不是我大学的集群 (Linux)。

我的编译器是:

Apple clang 版本 11.0.0 (clang-1100.0.33.17)

集群编译器是:

g++ (Spack GCC) 9.2.0

我的一个同事也安装了这个库并在他的机器上编译成功(总是 Mac)。

我试图将所有内容都减少到主要(我猜)错误,将所有内容都放在下面的代码中。

这里是错误:

error: invalid use of incomplete type 'class TensorBase<double, std::integer_sequence<long unsigned int, 0> >'
  116 |  class Matrix<Real,1,1,NonZeroRow_>: public TensorBase<Real, std::make_index_sequence<1>>

下面我放了代码。我基本上有一个 BaseTensor class 继承自 class Matrix。这样的class我也有专攻

#include <cstdlib>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <array>  


    using Integer=long;
    using Real=double;



    template <typename T, std::size_t>
    using getTypeSequence = T;



    template <typename, typename>
    class TensorBase;

    template <typename T, Integer ... Is>
    class TensorBase<T, std::index_sequence<Is...>>
    {
    protected:
        std::array<T, sizeof...(Is)> values{};
        static const std::size_t Size = sizeof...(Is);

    public:
        constexpr TensorBase (getTypeSequence<T, Is> ... vals)
        : values{{vals...}}
        {}

        constexpr TensorBase (std::array<T, sizeof...(Is)> const & a)
        : values{a}
        {}

        constexpr TensorBase (std::array<T, sizeof...(Is)> && a)
        : values{std::move(a)}
        {}

        // TensorBase(std::initializer_list<T> a)
        // {
        //     assert(a.size() == Size);
        //     std::copy(std::begin(a), std::end(a), std::begin(values));
        // }
 
        constexpr TensorBase () = default;

        ~TensorBase() = default;

        constexpr TensorBase (TensorBase const &) = default;
        constexpr TensorBase (TensorBase &&) = default;

        constexpr TensorBase & operator= (TensorBase const &) = default;
        constexpr TensorBase & operator= (TensorBase &&) = default;
    };


    template<typename T, Integer Rows_, Integer Cols_,Integer NonZeroRow_=-1>
    class Matrix: public TensorBase<T, std::make_index_sequence<Rows_*Cols_>> 
    {
    public:
        static constexpr Integer Rows=Rows_;
        static constexpr Integer Cols=Cols_;
        using type= Matrix<T,Rows,Cols>;
        using subtype=T;
        using MB = TensorBase<T, std::make_index_sequence<Rows*Cols>>;
        using MB::MB;
        using MB::values;
        static constexpr Integer NonZeroRow=NonZeroRow_;
        inline constexpr static Integer rows() { return Rows; }
        inline constexpr static Integer cols() { return Cols; }
        inline constexpr std::array<T,Rows*Cols> &operator()()
        {
            return values;
        }

        inline constexpr const std::array<T,Rows*Cols> &operator()()const
        {
            return values;
        }
        // access matrix direclty by using I*Col+J index
        inline constexpr T &operator()(const Integer i)
        {
            assert(i < Rows*Cols);
            return values[i];
        }

        inline constexpr const T &operator()(const Integer i)const
        {
            assert(i < Rows*Cols);
            return values[i];
        }

        inline constexpr T &operator()(const Integer i, const Integer j)
        {
            assert(i < Rows);
            assert(j < Cols);
            return values[i*cols() + j];
        }

        inline constexpr const T &operator()(const Integer i, const Integer j) const
        {
            assert(i < Rows);
            assert(j < Cols);
            return values[i*cols() + j];
        }
    };





    template<Integer NonZeroRow_>
    class Matrix<Real,1,1,NonZeroRow_>: public TensorBase<Real, std::make_index_sequence<1>> 
    {
    public:
        static constexpr Integer Rows=1;
        static constexpr Integer Cols=1;
        using T= Real;
        using type= Matrix<T,Rows,Cols>;
        using subtype=T;
        using MB = TensorBase<T, std::make_index_sequence<Rows*Cols>>;
        using MB::MB;
        using MB::values;
        static constexpr Integer NonZeroRow=NonZeroRow_;
        inline constexpr static Integer rows() { return Rows; }
        inline constexpr static Integer cols() { return Cols; }

        inline constexpr std::array<T,Rows*Cols> &operator()()
        {
            return values;
        }

        inline constexpr const std::array<T,Rows*Cols> &operator()()const
        {
            return values;
        }

        inline constexpr T &operator[](const Integer i)
        {
            assert(i < Rows);
            return values[i];
        }

        inline constexpr T &operator[](const Integer i)const
        {
            assert(i < Rows);
            return values[i];
        }


        // access matrix direclty by using I*Col+J index
        inline constexpr T &operator()(const Integer i)
        {
            assert(i < Rows*Cols);
            return values[i];
        }

        inline constexpr const T &operator()(const Integer i)const
        {
            assert(i < Rows*Cols);
            return values[i];
        }

        inline constexpr T &operator()(const Integer i, const Integer j)
        {
            assert(i < Rows);
            assert(j < Cols);
            return values[i*cols() + j];
        }

        inline constexpr const T &operator()(const Integer i, const Integer j) const
        {
            assert(i < Rows);
            assert(j < Cols);
            return values[i*cols() + j];
        }


    };

    int main(int argc, char *argv[])
    {

        constexpr Matrix<Real,1,1> mat{1.0};


    std::cout<<"it works"<<std::endl;
    static_assert(mat(0,0)==1.0);



    return 0;
    }

使用 integer_sequence<Integer, Is...> 而不是 index_sequence<Is...> 并在 Matrix<Real,1,1,NonZeroRow_> 中的 operator[] 的 return 中添加 const 为我修复了 gcc 10.1 中的构建错误。我真的不知道为什么使用整数序列来解决问题,但除了修复构建错误之外,在这种情况下行为应该是等效的。

这是我编辑后编译的版本 https://godbolt.org/z/dKHLDB

#include <cstdlib>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <array>  


using Integer=long;
using Real=double;



template <typename T, std::size_t>
using getTypeSequence = T;



template <typename, typename>
class TensorBase;

template <typename T, Integer ... Is>
class TensorBase<T, std::integer_sequence<Integer, Is...>>
{
protected:
    std::array<T, sizeof...(Is)> values{};
    static const std::size_t Size = sizeof...(Is);

public:
    constexpr TensorBase (getTypeSequence<T, Is> ... vals)
    : values{{vals...}}
    {}

    constexpr TensorBase (std::array<T, sizeof...(Is)> const & a)
    : values{a}
    {}

    constexpr TensorBase (std::array<T, sizeof...(Is)> && a)
    : values{std::move(a)}
    {}

    // TensorBase(std::initializer_list<T> a)
    // {
    //     assert(a.size() == Size);
    //     std::copy(std::begin(a), std::end(a), std::begin(values));
    // }

    constexpr TensorBase () = default;

    ~TensorBase() = default;

    constexpr TensorBase (TensorBase const &) = default;
    constexpr TensorBase (TensorBase &&) = default;

    constexpr TensorBase & operator= (TensorBase const &) = default;
    constexpr TensorBase & operator= (TensorBase &&) = default;
};


template<typename T, Integer Rows_, Integer Cols_,Integer NonZeroRow_=-1>
class Matrix: public TensorBase<T, std::make_integer_sequence<Integer, Rows_*Cols_>> 
{
public:
    static constexpr Integer Rows=Rows_;
    static constexpr Integer Cols=Cols_;
    using type= Matrix<T,Rows,Cols>;
    using subtype=T;
    using MB = TensorBase<T, std::make_integer_sequence<Integer, Rows*Cols>>;
    using MB::MB;
    using MB::values;
    static constexpr Integer NonZeroRow=NonZeroRow_;
    inline constexpr static Integer rows() { return Rows; }
    inline constexpr static Integer cols() { return Cols; }
    inline constexpr std::array<T,Rows*Cols> &operator()()
    {
        return values;
    }

    inline constexpr const std::array<T,Rows*Cols> &operator()()const
    {
        return values;
    }
    // access matrix direclty by using I*Col+J index
    inline constexpr T &operator()(const Integer i)
    {
        assert(i < Rows*Cols);
        return values[i];
    }

    inline constexpr const T &operator()(const Integer i)const
    {
        assert(i < Rows*Cols);
        return values[i];
    }

    inline constexpr T &operator()(const Integer i, const Integer j)
    {
        assert(i < Rows);
        assert(j < Cols);
        return values[i*cols() + j];
    }

    inline constexpr const T &operator()(const Integer i, const Integer j) const
    {
        assert(i < Rows);
        assert(j < Cols);
        return values[i*cols() + j];
    }
};





template<Integer NonZeroRow_>
class Matrix<Real,1,1,NonZeroRow_>: public TensorBase<Real, std::make_integer_sequence<Integer,1>> 
{
public:
    static constexpr Integer Rows=1;
    static constexpr Integer Cols=1;
    using T= Real;
    using type= Matrix<T,Rows,Cols>;
    using subtype=T;
    using MB = TensorBase<T, std::make_integer_sequence<Integer,Rows*Cols>>;
    using MB::MB;
    using MB::values;
    static constexpr Integer NonZeroRow=NonZeroRow_;
    inline constexpr static Integer rows() { return Rows; }
    inline constexpr static Integer cols() { return Cols; }

    inline constexpr std::array<T,Rows*Cols> &operator()()
    {
        return values;
    }

    inline constexpr const std::array<T,Rows*Cols> &operator()()const
    {
        return values;
    }

    inline constexpr T &operator[](const Integer i)
    {
        assert(i < Rows);
        return values[i];
    }

    inline constexpr const T &operator[](const Integer i)const
    {
        assert(i < Rows);
        return values[i];
    }


    // access matrix direclty by using I*Col+J index
    inline constexpr T &operator()(const Integer i)
    {
        assert(i < Rows*Cols);
        return values[i];
    }

    inline constexpr const T &operator()(const Integer i)const
    {
        assert(i < Rows*Cols);
        return values[i];
    }

    inline constexpr T &operator()(const Integer i, const Integer j)
    {
        assert(i < Rows);
        assert(j < Cols);
        return values[i*cols() + j];
    }

    inline constexpr const T &operator()(const Integer i, const Integer j) const
    {
        assert(i < Rows);
        assert(j < Cols);
        return values[i*cols() + j];
    }


};

int main(int argc, char *argv[])
{
constexpr Matrix<Real,1,1> mat{1.0};


std::cout<<"it works"<<std::endl;
static_assert(mat(0,0)==1.0);



return 0;
}

具体变化如下:

之前

template <typename T, Integer ... Is>
class TensorBase<T, std::index_sequence<Is...>>

之后

template <typename T, Integer ... Is>
class TensorBase<T, std::integer_sequence<Integer, Is...>>

之前

template<typename T, Integer Rows_, Integer Cols_,Integer NonZeroRow_=-1>
class Matrix: public TensorBase<T, std::make_index_sequence<Rows_*Cols_>> 

之后

template<typename T, Integer Rows_, Integer Cols_,Integer NonZeroRow_=-1>
class Matrix: public TensorBase<T, std::make_integer_sequence<Integer, Rows_*Cols_>> 

之前(在 Matrix

using MB = TensorBase<T, std::make_index_sequence<Rows*Cols>>;

之后

using MB = TensorBase<T, std::make_integer_sequence<Integer, Rows*Cols>>;

之前

template<Integer NonZeroRow_>
class Matrix<Real,1,1,NonZeroRow_>: public TensorBase<Real, std::make_index_sequence<1>> 

之后

template<Integer NonZeroRow_>
class Matrix<Real,1,1,NonZeroRow_>: public TensorBase<Real, std::make_integer_sequence<Integer, 1>> 

之前(在 Matrix<Real,1,1,NonZeroRow_>

using MB = TensorBase<T, std::make_index_sequence<Rows*Cols>>;

之后

using MB = TensorBase<T, std::make_integer_sequence<Integer, Rows*Cols>>;

之前(在 Matrix<Real,1,1,NonZeroRow_>

inline constexpr T &operator()(const Integer i)const

之后

inline constexpr const T &operator()(const Integer i)const