Rozumiem, że parametr szablonu innego niż typ powinien być stałym wyrażeniem integralnym. Czy ktoś może rzucić światło, dlaczego tak jest?
template <std::string temp>
void foo()
{
// ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.
Rozumiem, czym jest stała integralna ekspresja. Jakie są powody, dla których nie zezwalasz na typy niestałe, takie std::string
jak w powyższym fragmencie?
Odpowiedzi:
Nie możesz tego zrobić, ponieważ wyrażenia inne niż stałe nie mogą być analizowane i podstawiane w czasie kompilacji. Mogą się zmieniać w czasie wykonywania, co wymagałoby wygenerowania nowego szablonu w czasie wykonywania, co nie jest możliwe, ponieważ szablony są koncepcją czasu kompilacji.
Oto, na co pozwala standard dla parametrów szablonu innego niż typ (14.1 [temp.param] p4):
źródło
To nie jest dozwolone.
Jest to jednak dozwolone:
template <std::string * temp> //pointer to object void f(); template <std::string & temp> //reference to object void g();
Zobacz §14.1 / 6,7,8 w C ++ Standard (2003).
Ilustracja:
template <std::string * temp> //pointer to object void f() { cout << *temp << endl; } template <std::string & temp> //reference to object void g() { cout << temp << endl; temp += "...appended some string"; } std::string s; //must not be local as it must have external linkage! int main() { s = "can assign values locally"; f<&s>(); g<s>(); cout << s << endl; return 0; }
Wynik:
can assign values locally can assign values locally can assign values locally...appended some string
źródło
std::string
wskaźnika lub obiektu referencyjnego. Gdyby ta zmienna była lokalna, prawdopodobnie otrzymywałbyś różne adresy za każdym razem, gdy funkcja była wywoływana.Musisz umieć zmieniać argumenty szablonu
template <std::string temp> void f() { // ... } f<"foo">(); f<"bar">(); // different function!?
Teraz impl musiałby wymyślić unikalną sekwencję znaków dla a
std::string
lub, w tym przypadku, dowolnej innej dowolnej klasy zdefiniowanej przez użytkownika, przechowującej określoną wartość, której znaczenie nie jest znane implementacji. Ponadto wartości dowolnych obiektów klas nie można obliczyć w czasie kompilacji.Planuje się rozważyć dopuszczenie typów klas literałów jako typów parametrów szablonu dla post-C ++ 0x, które są inicjowane przez stałe wyrażenia. Mogłyby one zostać zniekształcone przez rekurencyjne zniekształcenie składowych danych zgodnie z ich wartościami (na przykład dla klas bazowych możemy zastosować przemierzanie w głąb, od lewej do prawej). Ale to na pewno nie zadziała dla dowolnych zajęć.
źródło
Argument szablonu inny niż typ podany na liście argumentów szablonu jest wyrażeniem, którego wartość można określić w czasie kompilacji. Takie argumenty muszą być:
Ponadto, literały łańcuchowe są obiektami połączonymi wewnętrznie, więc nie można ich używać jako argumentów szablonu. Nie możesz też użyć wskaźnika globalnego. Literały zmiennoprzecinkowe są niedozwolone, biorąc pod uwagę oczywistą możliwość błędów zaokrągleń.
źródło