9
#include<iostream>
using namespace std;

template<int N> class Prime
{ // generate N prime numbers at compile time
public:
    unsigned int arr[N]{};
    constexpr Prime() {
        int k=0;
        for(unsigned int i=2; k<N; i++) {
            bool isPrime = true;
            for(int j=0; j<k; j++) {
                if(arr[j] > i/2) break;
                if(i % arr[j] == 0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) arr[k++] = i;
        }
    }
};
int main()
{
    Prime<50000> prime; // if 50000->5000, ok
    for(auto& a : prime.arr) cout << a << ' ';
}

G++ fails to compile this code. It spends ages trying to compile, uses lots of memory, and finally just crashes.

If I make the number 50000 smaller, or get rid of constexpr, it compiles. But I want to use bigger arrays to save time.

Any ideas will be appreciated.

Boann
  • 48,794
  • 16
  • 117
  • 146
Zeta
  • 913
  • 10
  • 24
  • What error do you see? – Soren Feb 20 '17 at 02:03
  • 2
    situation is like this. compiler takes forever to compile. using lots of memories and finally just crashes.. – Zeta Feb 20 '17 at 02:05
  • 10
    You're asking gcc to find all the prime numbers between 1 and 50000, itself, using metaprogramming. Quite impressive, but this is not what compilers are meant to be used for. You, sir/m'am, won the Internets today. – Sam Varshavchik Feb 20 '17 at 02:05
  • ... Really, this deserves an upvote just for the awesomeness ... – Sam Varshavchik Feb 20 '17 at 02:07
  • @SamVarshavchik -- maybe we can finally put to rest all the arguments about if compiled Java or C++ is fater – Soren Feb 20 '17 at 02:10
  • Damn right. I'd like to see a Java compiler try to do something like this. Good. fracking. luck. – Sam Varshavchik Feb 20 '17 at 02:11
  • @Parker: ...And next time you'll write a program that computes the answer to "The Question of Life the Universe and Everything" *at compile time* and expect it to finish compiling while you are making yourself a cup of coffee? – AnT stands with Russia Feb 20 '17 at 02:14
  • @AnT If you try that g++ fails to compile it, but offers to build a more powerful compiler that is capable of doing the task. And it shall be called... clang – Jeremy Friesner Feb 20 '17 at 02:19
  • 1
    @AnT Coffee? More like a drink that tastes almost, but not quite, exactly unlike tea. – Barry Feb 20 '17 at 02:24
  • In 7 and a half million years there will still be people using C89 because the vender hasn't got around to supporting C99 yet – M.M Feb 20 '17 at 02:35
  • The code compiles given any number without any problem, but it is crashing at run time. – Mahmoud Fayez Feb 20 '17 at 03:16
  • works on Clang 3.4 and higher – TemplateRex Feb 20 '17 at 07:40
  • 4
    If you actually do need the first 50000 prime numbers I'd suggest to compute or download them offline and store them in a constexpr variable. This is kust wasted compiletime. – MikeMB Feb 20 '17 at 07:59
  • GCC clearly uses too much memory for this, but this is still a total waste of time and electricity. The primes aren't going to change, you don't need to recalculate them every time you compile. Write a (non-compile-time!) program to print them, save that in a header file, and include it in your code. – Jonathan Wakely Feb 20 '17 at 23:24

1 Answers1

6

This is a Quality of Implemention (QoI) matter. From the draft Standard

Annex B (informative) Implementation quantities [implimits]

1 Because computers are finite, C++ implementations are inevitably limited in the size of the programs they can successfully process. Every implementation shall document those limitations where known. This documentation may cite fixed limits where they exist, say how to compute variable limits as a function of available resources, or say that fixed limits do not exist or are unknown.

2 The limits may constrain quantities that include those described below or others. The bracketed number following each quantity is recommended as the minimum for that quantity. However, these quantities are only guidelines and do not determine compliance.

(2.38) — Recursive constexpr function invocations [512].

(2.39) — Full-expressions evaluated within a core constant expression [1 048 576].

Your algorithm exceeds the limit of full-expressions evaluated within a core constant expression. Note that gcc does exceed the minimum requirement since your loop scales as 1/2 * N^2 and gcc compiles it for N = 5,000. I haven't been able to find the documented hard limit for gcc. Unfortunately, and unlike clang which has -fconstexpr-steps, you cannot override the number of constexpr evaluations for gcc.

Conclusion: submit a performance report to gcc or use clang (for which your example does compile).

TemplateRex
  • 69,038
  • 19
  • 164
  • 304