2013-08-13 4 views
5

Mam pewien ogólny kod, który musi uruchomić asercję na wynik funkcji składowej. Ta funkcja składowa może być constexpr lub może nie być.Makro assert, które rozwija się do static_assert, gdy jest to możliwe?

template<typename T> 
void foo(T t) { 
    assert(t.member_function() == 10); 
} 

Ponieważ t.member_function()może być stałym wyrażeniem, zastanawiam się, czy to możliwe, aby być traktowane jako static_assert w takich przypadkach, ale w przeciwnym razie domyślnie normalny assert. czy to możliwe?

+1

Podobny do http://stackoverflow.com/q/11441302/560648. Nie jestem pewien, czy to dotyczy. –

+3

http://stackoverflow.com/q/6939103/560648 jest bliżej, i [mówi, że odpowiedź brzmi "nie"] (http://stackoverflow.com/a/6941680/560648). –

+1

[stackoverflow.com/questions/18648069](http://stackoverflow.com/questions/18648069/g-doesnt-compile-constexpr-function-with-assert-in-it) jest jeszcze bliżej i mówi "tak, ale " –

Odpowiedz

1

To nieco szalone rozwiązanie.

Odkomentuj linię Const c; foo(c);, a zobaczysz, że się nie skompiluje. To jest kompilacja asertywna.

Wymaga to variable length arrays i może innych rzeczy specyficznych dla kompilatora. Jestem na g ++ - 4.6.

Wielkość tablicy wynosi 0 lub -1, w zależności od tego, czy funkcja członkowska zwraca wartość 10. Tak więc, jeśli można ją obliczyć w czasie kompilacji, wówczas kompilacja zdaje sobie sprawę, że jest to tablica o zmiennej długości, a także ma rozmiar ujemny. Ujemny rozmiar pozwala mu narzekad. W przeciwnym razie przechodzi do konwencjonalnego dowodu.

Uwaga: Dostaję zrzut rdzenia z wersją środowiska wykonawczego zaraz po niepowodzeniu asercji środowiska wykonawczego. Być może nie podoba mi się próbowanie free tablicy o rozmiarze ujemnym. Aktualizacja: Otrzymuję zrzuty pamięci z niepowodzeniem asercji, nawet int main() {assert (1==2);}. Czy to normalne?

#include <iostream> 
#include <cassert> 
using namespace std; 

struct Const { 
     constexpr int member_function() { return 9; } 
}; 
struct Runtime { 
        int member_function() { return 9; } 
}; 

template<typename T> 
void foo(T t) { 
     if(0) { // so it doesn't actually run any code to malloc/free the vla 
      int z[(t.member_function()==10)-1]; // fails at compile-time if necessary 
     } 
     assert(t.member_function()==10); 
} 


int main() { 
     //Const c; foo(c); 
     Runtime r; foo(r); 
}