2016-12-06 27 views
7

Myślę, że to niemożliwe, ale chciałbym zapytać, zanim się poddasz.Kradzieże Constexpr

Chcę coś podobnego do przyrostu constexpr.

#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; 
} 

chcę nazywać go w niektórych klasach nie ręcznie (używam CRTP za to), aby dać inny typ każdego z nich, ale typ muszą być const. Jest coś takiego, aby osiągnąć coś takiego w C++? (C++ 17 + TS)

+3

* "Myślę, że to niemożliwe" * Zasadniczo wszystko jest możliwe dzięki szablonom C++, czasami robi się głupio złożony. –

+0

Nie jestem pewien, ale myślę, że może być częścią C++ 17, ale mogę się mylić – holmicz

+3

Istnieją niestandardowe makra 'COUNTER' i istnieją implementacje efektów ubocznych kompilacji ([Filip Roseen ] (http://b.atch.se/) przychodzi na myśl). Te ostatnie są jednak wyjątkowo brzydkie. Wolałbym spróbować innego podejścia. – dyp

Odpowiedz

1

Więc nie jest to rozwiązanie przez Filip Roseen zwany constant-expression counter:

#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; 
} 

Dzięki chłopaki :) Ale to zbyt ryzykowne do stosowania go w moim głównej biblioteki, która będzie używać w każdym projekcie.

PS: Nie zamknę tego teraz, jeśli istnieje inna odpowiedź. Ponieważ tak, to jest brzydkie.