1

I am doing some very basic problems to get familiar with Template Metaprogramming. This one in particular is just to add up the values on the down-right diagonal of a square matrix (indexes of [0,0],[1,1], etc.). I have solved this in many ways with different constexpr functions, but I do not understand why one particular way fails. Code and error message below:

constexpr int DRsum(const int* starter, const size_t size, int itr = 0)
{
    if(itr==size-1)
    {
        return *starter;
    }
    size_t sum = 0;
    sum = *starter;
    sum += DRsum(starter+size+1, size, itr+1);
    return sum;
}

int main()
{
    static const size_t size = 3;

    static constexpr const int matrix[][size] = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
    };

    static constexpr int const* baseptr = &matrix[0][0];

    constexpr int sum = DRsum(baseptr, size);
}

The error message is as follows:

main.cpp|69|  in constexpr expansion of 'DRsum((& matrix[0][0]), 3u, 0)'|
main.cpp|39|  in constexpr expansion of 'DRsum((starter + ((((sizetype)size) + 1u) * 4u)), 
    ((size_t)size), (itr + 1))'|
main.cpp|69|error: '* starter' is not a constant expression|

I am not sure why this is doing this, as I am new to Template Metaprogramming. I made a dummy function to test if the pointer dereference was the issue, and that worked out fine. My guess is that it might have to do with me passing in a pointer rather than a pointer to a constexpr pointer, but I'm not sure. Any help would be appreciated, Thanks.

Also, I have already solved this by means of just passing in the entire structure (just straight up a deep copy) but I would rather know how to pass things by shallow copy or pointer into constexpr functions. Thanks.

5
  • 1
    The pointer is not constant, what it points to is constant in your declaration, so there's one misconception. Secondly, you talk about template metaprogramming, but there is no template involved here!? Commented Aug 11, 2018 at 12:03
  • Even with the added const after the * in both the function argument list and the pointer declaration, it still gives me the error message "main.cpp|68|error: '(const int)starter' is not a constant expression|". Basically i redefined baseptr from static constexpr int const* to static constexpr int const* const (which I thought constexpr implied for a pointer anyway). Commented Aug 11, 2018 at 12:17
  • @SaswatMishra Which compiler are you using? gcc is fine, except that you are accessing the array out of its bounds godbolt.org/g/4M2sG3 Commented Aug 11, 2018 at 12:20
  • @vdavid Im using GCC 5.1.0, and I'm pretty sure the "out of bounds" error message is a compiler misinterpretation of some other error that I am making, since when I change the variable declaration at the bottom from "constexpr int sum" to "int sum" (making DRsum run at runtime), everything works fine and I get the correct values. The function logic (as far as index access) is fine, my compiler just throws a fit about starter not being a constant expression. Commented Aug 11, 2018 at 12:48
  • There is no templates in the question so I removed template-related tags. If you disagree, feel free to roll back. Commented Aug 11, 2018 at 12:58

1 Answer 1

0

A 2D array (matrix) cannot be treated as a 1D array, so starter+size+1 results in undefined behavior. Usually undefined behavior is undefined so the program may work as expected, but when an undefined behavior happens within a structure that requires a constant expression, the program becomes ill-formed thus the compiler emits an error.

I don't think there is a simple fix because there is no well-defined way to access the whole 2D array through starter (even with std::launder), unless you change the signature of DRsum. For example, you can write DRsum as follows:

template <size_t size>
constexpr int DRsum(const int (*starter)[size], int itr = 0)
{
    if (itr == size - 1)
    {
        return (*starter)[itr];
    }
    size_t sum = 0;
    sum = (*starter)[itr];
    sum += DRsum(starter + 1, itr + 1);
    return sum;
}

then call it like constexpr int sum = DRsum(matrix);.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.