1

Building on the answer I got to my question Constexpr Class taking const references not compiling, I was trying go further (playing around with expression templates).

So as the answer suggested, I now use static variables as inputs, and everything compiles correctly (on MSVC 2019).

However, upon adding constexpr static auto val = expr[0] I get error C2131: expression did not evaluate to a constant. The issue seems to be with m_lhs[idx] and m_rhs[idx] as those do not seem to evaluate to a constant, despite the fact that i've marked all operator[] as constexpr.

Is it possible to fix this?

#include <cstddef>

template<class VecType>
struct Vector
{
    constexpr const VecType& get() const noexcept
    {
        return static_cast<const VecType&>(*this);
    }
};

template<size_t Size>
class FixedSizeVector : public Vector<FixedSizeVector<Size>>
{
public:
    constexpr explicit FixedSizeVector(const int(&array)[Size]) noexcept
        : m_vector()
    {
        for (size_t i = 0; i < Size; ++i)
            m_vector[i] = array[i];
    }

    constexpr const int& operator[](size_t idx) const noexcept {
        return m_vector[idx];
    }

private:
    int m_vector[Size];
};

template<class VecType1, class VecType2>
class ExpressionAdd : public Vector<ExpressionAdd<VecType1, VecType2>>
{
public:
    constexpr ExpressionAdd(const VecType1& lhs, const VecType2& rhs) noexcept
        : m_lhs(lhs), m_rhs(rhs) { }

    constexpr int operator[](size_t idx) const noexcept {
        return m_lhs[idx] + m_rhs[idx];
    }

private:
    const VecType1& m_lhs;
    const VecType2& m_rhs;
};

template<class VecType1, class VecType2>
constexpr auto operator+(const Vector<VecType1>& lhs, const Vector<VecType2>& rhs)
{
    return ExpressionAdd(lhs.get(), rhs.get());
}


int main()
{
    constexpr static int arr[]{ 4,2,9 };
    constexpr static FixedSizeVector a(arr);

    constexpr static auto expr = a + a;
    constexpr static auto val  = expr[0];  /* <--- this line causes an error */

    return 0;
}

Phil-ZXX
  • 2,359
  • 2
  • 28
  • 40
  • 1
    MSVC bug. Looks good to me and compiles on gcc and clang. – Barry Aug 20 '19 at 23:39
  • It appears to be caused by the combination of the get() function and the base Vector class casting. This compiles: https://godbolt.org/z/7Cmmgt. I changed the operator+ to accept any type ( I suspect you don't want that, perhaps use enable_if for your use case ). You could use it with: https://en.cppreference.com/w/cpp/types/is_base_of – David Ledger Aug 22 '19 at 14:40

0 Answers0