2016-12-06 8 views
7

Я думаю, что это невозможно, но я хотел бы спросить вас, прежде чем сдаваться.Constexpr трюки

Я хочу что-то вроде приращения 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; 
} 

Я хочу назвать его в некоторых классах не вручную (я использую CRTP для этого), чтобы дать другой тип для каждого из них, но тип должен быть константной. В любом случае, для достижения чего-либо подобного в C++? (C++ 17 + TS)

+3

* «Я думаю, что это невозможно» * В принципе все возможно с шаблонами C++, иногда это иногда становится глупо сложным. –

+0

Я не уверен, но я думаю, что это может быть часть C++ 17, но я могу ошибаться – holmicz

+3

Существуют нестандартные макросы 'COUNTER', и есть реализации побочных эффектов компиляции ([Filip Roseen ] (http://b.atch.se/) приходит на ум). Однако последние крайне уродливы. Я предпочел бы попробовать другой подход. – dyp

ответ

1

Таким образом, есть решение по Filip Roseen называется 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; 
} 

Спасибо, ребята :) Но это слишком рискованно использовать его в моей главной библиотеке, которая будет использовать в каждом проекте.

PS: Я не буду закрывать это прямо сейчас, если есть другой ответ. Потому что да, это уродливо.

 Смежные вопросы

  • Нет связанных вопросов^_^