2016-08-30 19 views
9

Pytanie: czy możliwe jest oszacowanie stałego wyrażenia wewnątrz funkcji poprzez przekazanie (być może z pewnym "doskonałym przekazywaniem") jego argumentu do wewnętrznej funkcji constexpr? Przykład:Czy istnieje sposób przekazania argumentu do wewnętrznej funkcji constexpr?

constexpr size_t foo(char const* string_literal) { 
    return /*some valid recursive black magic*/; 
} 

void bar(char const* string_literal) { 
    // works fine 
    constexpr auto a = foo("Definitely string literal."); 
    // compile error: "string_literal" is not a constant expression 
    constexpr auto b = foo(string_literal); 
} 

template<typename T> 
void baz(T&& string_literal) { 
    // doesn't compile as well with the same error 
    constexpr auto b = foo(std::forward<T>(string_literal)); 
} 

int main() { 
    // gonna do this, wont compile due to errors mentioned above 
    bar("Definitely string literal too!"); 
} 

nie mogę znaleźć nic wyraźnie zakazują w documentation, ale rozwiązanie nie zostanie znalezione, a także dowód niemożności. Konkretyzacja wewnętrznej ekspresji jest ważna.

+0

https://stackoverflow.com/questions/26582875/constexpr-function-parameters-as-template-arguments – SomeWittyUsername

Odpowiedz

7

Parametry do constexpr funkcji nie mogą być uznane za constexpr w ramach funkcji constexpr; funkcja musi działać , jeśli nie są one constexpr.

Parametry typu mogą być.

Jeśli zastąpiono bar("hello") przez bar(string_constant<'h', 'e', 'l', 'l', 'o'>{}) z template<char...>struct string_constant{};, wartość znaków jest teraz zakodowana w typie i będzie dostępna w ścieżce. Istnieją inne sposoby na wprowadzenie postaci do postaci.

2

Niestety, nie można tego osiągnąć. Parametry funkcji constexpr również nie są automatycznie constexpr. Funkcja może być mimo wszystko wywołana z kontekstu innego niż constexpr. Twój kompilator może być w stanie zoptymalizować twoją sprawę do oceny w czasie kompilacji, ale to w żaden sposób nie jest gwarantowane.

Istnieje stałe obejście, w którym można użyć parametrów szablonu, aby wymusić rodzaj parametru o wartości constexpr -ness. Dobry przykład można znaleźć pod adresem this question. Opierając się na tym, można by ulec pokusie, aby to zrobić:

template<const char * string_literal> void baz() { 
    constexpr auto b = foo(string_literal); 
} 

int main() { 
    baz<"Definitely string literal too!">(); 
} 

Jednak ta pochodzi z ograniczeniami na parametry szablonu nie typu, z których jeden mówi, że Łańcuch znaków nie może być parametrem szablonu non-type. Możesz użyć szablonu variadic, zgodnie z sugestią Yakk, jeśli można go zastosować do twojego przypadku.

Obsługa parametrów funkcji constexpr może zostać dodana w przyszłości. Istnieje dyskusja na temat grup dyskusyjnych ISO C++ here.

Możesz także przekonwertować baz na jakieś sparametryzowane makro, jeśli naprawdę potrzebujesz wykonać zadanie .