3

Lets assume I want to write struct that has a member constexpr std::array that contains first N fibs, where N is a template argument.

Something like this but with vals being avaliable at compile time:

template <int N>
struct first_n_fibs {
    static_assert(N>0);
    static const std::array<int, N> vals;
    static std::array<int, N> init_fibs(){
        std::array<int,N> result;
        if (N==1) {
            return std::array<int,N>{1};
        } else {
            result[0]=1;
            result[1]=1;
            for(int i =2; i<N;++i) {
                result[i]=result[i-2]+result[i-1];
            }
        }
        return result;
    }
};

template<int N>
const std::array<int, N> first_n_fibs<N>::vals=init_fibs();


int main(){
    std::cout << first_n_fibs<2>::vals.back() << std::endl;
    std::cout << first_n_fibs<5>::vals.back() << std::endl;
    std::cout << first_n_fibs<6>::vals.back() << std::endl;
}

I suspect there is no workaround since std::array constructors are not constexpr, so if somebody knows any workarounds involving C arrays or boost I would be happy with that.

4
  • I'd like to know why you want it to be std::array. Besides, first_n_fibs<n> create a lot of instance while all these are (prefix) equal. Commented May 10, 2018 at 0:52
  • because IDK how to operate on C array at compile time. As for instances and duplication: I know about that, but in some cases it is worth the cost. Commented May 10, 2018 at 0:56
  • if you work on C array than any prefix-equal const first_n_fibs can be represent by single pointer to the longest array. can you provide your use case? Commented May 10, 2018 at 1:02
  • otherwise if you want to get only the nth-fib at compile time a std::array may be overkill. Commented May 10, 2018 at 1:08

2 Answers 2

7

You don't need anything special, constexpr function requirements are very relaxed these days:

#include <iostream>
#include <array>

template <int N> constexpr std::array<int, N> first_n_fibs()
{
    std::array<int, N> ret{};
    ret[0] = 0;
    if (N == 1) return ret;
    ret[1] = 1;
    for (int i = 2; i < N; i++)
        ret[i] = ret[i-2] + ret[i-1];
    return ret;
}

int main()
{
    constexpr auto a = first_n_fibs<3>();
}

(try it live)


std::array constructors are not constexpr

Apparently it has no user-defined constructors at all, so nothing stops its construction from being constexpr.

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

2 Comments

nice workaround, but in general I prefer to have it inside class, since having a bunch of "getter" functions is not nice(and may be slower) from design point of view.
Actually you are right, gcc was giving me lame error, all I did was that I did not initializer ret with {} like you did.
2

You can use immediately called lambda:

struct foo {
    static constexpr auto arr = []{
        std::array<int, 6> a{};

        for (auto& e : a) {
            // stuff
        }

        return a;
    }();
};

But as HolyBlackCat said, std::array is constexpr constructible, since it has no defined constructor, only compiler defined ones.

Here's live example at coliru

5 Comments

"std::array is totally constexpr constructible" IDK the language terms, but when I put constexpr in front of member it does not compile :)
"error: constexpr static data member 'vals' must have an initializer"
@NoSenseEtAl when making a variable constexpr, you must give it a value, as your compiler is telling you. It needs an initializer. Alternatively, you can put your definition inline and mark the definition add constexpr.
Plese see my other comments, bug was me not writing {} when initializing array in my function, and GCC giving me silly error.
I still upvoted your answer, I am sorry you wasted time on helping me, but really error smelled like constexpr problem(it contained "is not usable as a constexpr function because")

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.