2016-12-06 5 views
7

Ich denke, dass es nicht möglich ist, aber ich möchte dich fragen, bevor du darüber aufgibst.Constexpr Tricks

Ich möchte so etwas wie ein Constexpr Inkrement.

#include <iostream> 

constexpr int inc() { 

    static int inc = 0; 
    return inc++; 
} 

class Foo { 

    static const int Type = inc(); 
}; 

class Foo2 { 

    static const int Type = inc(); 
}; 

int main() { 

    std::cout << "Foo1 " << Foo1::Type << st::endl; 
    std::cout << "Foo2 " << Foo2::Type << st::endl; 
    return 0; 
} 

Ich will es in einigen Klassen nennen nicht manuell (ich benutze CRTP dafür), eine andere Art zu jedem von ihnen zu geben, aber die Art müssen const sein. Gibt es in C++ sowieso sowas zu erreichen? (C++ 17 + TS)

+3

* "Ich denke, es ist nicht möglich" * Grundsätzlich ist alles mit C++ - Vorlagen möglich, es wird manchmal einfach dumm komplex. –

+0

Ich bin mir nicht sicher, aber ich denke, es könnte ein Teil von C++ 17 sein, aber ich kann falsch liegen – holmicz

+3

Es gibt nicht-Standard 'COUNTER' Makros, und es gibt Implementierungen von Kompilierzeit Nebenwirkungen ([Filip Roseen ] (http://b.atch.se/) fällt mir ein). Letztere sind jedoch extrem hässlich. Ich würde lieber einen anderen Ansatz ausprobieren. – dyp

Antwort

1

So gibt die Lösung von Filip Roseen ist die constant-expression counter genannt:

#include <iostream> 

template<int N> 
struct flag { 
    friend constexpr int adl_flag (flag<N>); 
}; 

template<int N> 
struct writer { 
    friend constexpr int adl_flag (flag<N>) { 
    return N; 
    } 

    static constexpr int value = N; 
}; 

template<int N, int = adl_flag (flag<N> {})> 
int constexpr reader (int, flag<N>) { 
    return N; 
} 

template<int N> 
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1> {})) { 
    return R; 
} 

int constexpr reader (float, flag<0>) { 
    return 0; 
} 

template<int N = 1> 
int constexpr next (int R = writer<reader (0, flag<32> {}) + N>::value) { 
    return R; 
} 

class Foo { 

    public: 
    static const int Type = next(); 
}; 

class Foo2 { 

    public: 
    static const int Type = next(); 
}; 

int main() { 

    std::cout << "Foo1 " << Foo::Type << std::endl; 
    std::cout << "Foo2 " << Foo2::Type << std::endl; 
    return 0; 
} 

Danke Jungs :) Aber es ist zu riskant für die Verwendung in meiner Haupt-Bibliothek, die sein wird, Verwenden Sie in jedem Projekt.

PS: Ich werde das jetzt nicht schließen, wenn es eine andere Antwort gibt. Denn ja, es ist hässlich.