2014-12-21 24 views
8

Byłoby użyteczne mieć parametry "constexpr" w celu odróżnienia wartości znanych od kompilatora, aby móc wykryć błędy podczas kompilacji. Przykłady:Dlaczego parametry "constexpr" są niedozwolone?

int do_something(constexpr int x) 
{ 
    static_assert(x > 0, "x must be > 0"); 
    return x + 5; 
} 

int do_something(int x) 
{ 
    if(x > 0) { cout << "x must be > 0" << endl; exit(-1); } 
    return x + 5; 
} 

int var; 

do_something(9); //instance 'do_something(constexpr int x)' and check arg validity at compile-time 

do_something(0); //produces compiler-error 

do_something(var); //instance 'do_something(int x)' 

Który jest teraz nieprawidłowy. Czy ktoś może mi wyjaśnić, dlaczego nie można tego zrealizować?

EDIT:

pomocą szablonów użytkowników powinny zapewnić, że literały są zawsze przekazywane jako argumenty szablonu, a nie te, które działają bardzo niewygodne:

template<int x> 
int do_something() 
{ 
    static_assert(x > 0, "x must be > 0"); 
    return x + 5; 
} 

int do_something(int x) 
{ 
    if(x > 0) { cout << "x must be > 0" << endl; exit(-1); } 
    return x + 5; 
} 

int var; 

do_something(9); //instance 'do_something(int x)' and doesn't checks validity at compile-time 

do_something(0); //same as above, if check was performed - compiler error should occur 

do_something<9>(); //instance template 'do_something<int>()' 

do_something<0>(); //produces compiler error 

do_something(var); //instance 'do_something(int x)' 
+1

Czy możesz już to zrobić za pomocą szablonu? W szczególności z parametrami szablonu non-type? – Borgleader

+0

Następnie użytkownik mojej funkcji powinien dostarczyć inną składnię do wywoływania go w zależności od tego, czy parametr jest znany w czasie kompilacji. – AnArrayOfFunctions

+0

Prawdopodobieństwo, że assert() zostanie zoptymalizowane w przypadku przekazania wartości constexpr. –

Odpowiedz

-4

Choć brzmi świetnie w teorii, to nie tak przydatne w realnym świecie. Większość argumentów funkcji nie jest kompilacją stałych czasowych, a wiele ograniczeń nie jest dokładnie znanych w czasie kompilacji.

Określenie i wdrożenie takiego przeciążenia będzie wymagało znacznej ilości pracy i nie będzie używane tak dużo. Kiedy faktycznie masz granice czasu kompilacji i argumenty, zazwyczaj możesz ocenić całą funkcję w czasie kompilacji, co oznacza, że ​​przeciążanie nie jest konieczne.

+1

Nie odpowiada to konkretnie DLACZEGO, o co pyta. – cybermonkey

+0

@cybermonkey Oczywiście nie zgadzam się. Próbowałem wyjaśnić, dlaczego funkcja nie jest w standardzie, opisując, dlaczego nie jest ona wystarczająco użyteczna, aby uzasadnić wysiłek.W przeciwieństwie do innej odpowiedzi na to pytanie, która nie odpowiada na pytanie, dlaczego w jakikolwiek sposób, kształt lub forma, ale po prostu próbuje opisać obejście (tj. Umieszcza rzeczywisty kod, który po prostu pokazuje to, co piszę w drugim akapicie). –

2

Jeśli dobrze rozumiem, co próbujesz zrobić poprawnie, żądana funkcja jest już dostępna. To nie jest najbardziej eleganckie, ale myślę, że to wystarczy.

Chciałbyś wywołać funkcję w czasie kompilacji i pracy z tą samą składnią, i jeśli to możliwe, powinna ona być oceniana w czasie kompilacji, w przeciwnym razie powinna być oceniana w czasie wykonywania. Potrzebujesz asercji do oceny na funkcji, niezależnie od tego, kiedy zostanie wywołana.

Wierzę, że będzie to robić co chcesz:

constexpr int do_something(int x) 
{ 
    if(x <= 0) 
    { 
     std::cout << "x must be > 0" << std::endl; exit(-1); 
    } 
    return x + 5; 
} 

constexpr int compiletime_good = do_something(5); 
constexpr int compiletime_bad = do_something(0); // Fails at compile-time 

int runtime_good = do_something(5); 
int runtime_bad = do_something(0); // Fails at runtime 

constexpr int val_good = 5; 
constexpr int val_bad = 0; 

do_something(val_good); 
do_something(val_bad); // Fails at run-time 

int valrun_good = 5; 
int valrun_bad = 0; 

do_something(valrun_good); 
do_something(valrun_bad); // Fails at run-time 

Sztuką jest tu nie w czasie kompilacji w sposób, który nie wymaga static_assert, a także nie w czasie wykonywania.

+1

Który będzie wymagał wywołania każdej instancji "do_something" tam, gdzie oczekiwane jest "constexpr", co nie jest lepsze niż użycie szablonów. – AnArrayOfFunctions

+0

@FISOCPP Odpowiednio. Zgaduję, że powodem, dla którego nie mamy wyraźnego sposobu na zawarcie parametrów constexpr w sposób, o jaki prosisz, jest to, że nikt nie zadał sobie trudu, aby napisać i dostać propozycję przepchniętą. Chciałbym, żeby tak się stało, ale brzmi to jak dużo pracy. –

+1

Należy oczywiście użyć istniejącego obiektu do zgłaszania błędu asercji, a nie posypywać wywołań 'std :: exit()' w całym zakresie kodów. W przeciwnym razie jest to bardzo dobre. –

Powiązane problemy