constexpr, static_assert i inlining

Wcześniej pytałem oprzeciążenie funkcji na podstawie tego, czy argumenty sąconstexpr. Próbuję obejść rozczarowującą odpowiedź na to pytanie, aby stworzyć mądrzejszą funkcję asercji. To jest mniej więcej to, co próbuję zrobić:

<code>inline void smart_assert (bool condition) {
    if (is_constexpr (condition))
        static_assert (condition, "Error!!!");
    else
        assert (condition);
}
</code>

Zasadniczo chodzi o to, że sprawdzanie w czasie kompilacji jest zawsze lepsze niż sprawdzanie w czasie wykonywania, jeśli możliwe jest sprawdzenie w czasie kompilacji. Jednak ze względu na takie rzeczy, jak wstawianie i ciągłe składanie, nie zawsze wiem, czy możliwe jest sprawdzenie czasu kompilacji. Oznacza to, że mogą wystąpić przypadkiassert (condition) kompiluje doassert(false) a kod tylko czeka, aż go uruchomię i wykonam tę ścieżkę, zanim stwierdzę, że wystąpił błąd.

Dlatego, jeśli był jakiś sposób, aby sprawdzić, czy warunek jest constexpr (z powodu wstawiania lub innych optymalizacji), mógłbym zadzwonićstatic_assert kiedy to możliwe, i wycofać się w czasie run twierdzą inaczej. Na szczęście gcc ma wewnętrzną__builtin_constant_p (exp), która zwraca wartość true, jeśliexp jest constexpr. Nie wiem, czy inne kompilatory mają to samo, ale miałem nadzieję, że to rozwiąże mój problem. Oto kod, który wymyśliłem:

<code>#include <cassert>
#undef IS_CONSTEXPR

#if defined __GNUC__
    #define IS_CONSTEXPR(exp) __builtin_constant_p (exp)
#else
    #define IS_CONSTEXPR(exp) false
#endif
// TODO: Add other compilers

inline void smart_assert (bool const condition) { 
    static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!");
    if (!IS_CONSTEXPR(condition))
        assert (condition);
}

#undef IS_CONSTEXPR
</code>

Thestatic_assert polega na zwarciuor. JeśliIS_CONSTEXPR to prawdastatic_assert może być używany, a warunek jest!true or condition, który jest taki sam jak po prostucondition. JeśliIS_CONSTEXPR jest więc fałszywestatic_assert nie można użyć, a warunek jest!false or condition, który jest taki sam jaktrue istatic_assert jest ignorowany. Jeślistatic_assert nie można sprawdzić, ponieważcondition nie jest constexpr, a następnie dodaje czas wykonywaniaassert do mojego kodu jako ostatni wysiłek. Jednak to nie działabrak możliwości użycia argumentów funkcji w astatic_assert, nawet jeśli argumenty sąconstexpr.

W szczególności dzieje się tak, gdy próbuję skompilować z gcc:

<code>// main.cpp
int main () {
    smart_assert (false);
    return 0;
}
</code>

g++ main.cpp -std=c++0x -O0

Wszystko jest w porządku, kompiluje się normalnie. Nie ma wstawiania bez optymalizacji, więcIS_CONSTEXPR jest fałszywe istatic_assert jest ignorowany, więc po prostu otrzymuję czas wykonaniaassert oświadczenie (to się nie udaje). Jednak,

<code>[david@david-desktop test]$ g++ main.cpp -std=c++0x -O1
In file included from main.cpp:1:0:
smart_assert.hpp: In function ‘void smart_assert(bool)’:
smart_assert.hpp:12:3: error: non-constant condition for static assertion
smart_assert.hpp:12:3: error: ‘condition’ is not a constant expression
</code>

Jak tylko włączę wszelkie optymalizacje i tym samym potencjalnie pozwolęstatic_assert aby zostać uruchomionym, zawodzi, ponieważ nie mogę użyć argumentów funkcji wstatic_assert. Czy jest jakiś sposób na obejście tego problemu (nawet jeśli oznacza to wdrożenie własnegostatic_assert)? Uważam, że moje projekty C ++ mogą teoretycznie przynieść spore korzyści z inteligentniejszego stwierdzenia assert, które wychwytuje błędy tak szybko, jak to możliwe.

To nie wygląda na robieniesmart_assert makro podobne do funkcji rozwiąże problem w ogólnym przypadku. Będzie to oczywiście działać w tym prostym przykładzie, alecondition może pochodzić z funkcji dwóch poziomów wykresu wywołania (ale nadal staje się znana kompilatorowi jakoconstexpr z powodu wstawiania), który napotyka ten sam problem z użyciem parametru funkcji w astatic_assert.

questionAnswers(3)

yourAnswerToTheQuestion