2016-08-01 21 views
1

Ich habe vor kurzem angefangen, mit Vorlage Metaprogrammierung in C++ zu spielen, und versucht, die Länge einer C-Stil-Zeichenfolge zu bewerten.Hatte obere Grenze während der Bewertung der Länge der C-Stil-Zeichenfolge durch Vorlage Metaprogrammierung

Ich habe einige Erfolge mit diesem Stück Code jedoch

template <const char *str, std::size_t index> 
class str_length { 
public: 
    static inline std::size_t val() { 
     return (str[index] != '\0') ? (1 + str_length<str, index + 1>::val()) :    0; 
    } 
}; 

template <const char *str> 
class str_length <str, 500> { 
public: 
    static inline std::size_t val() { 
     return 0; 
    } 
}; 

extern const char bitarr[] { "0000000000000000000" }; 

int main() { 
    std::cout << str_length<bitarr, 0>::val() << std::endl; 

    getchar(); 
    return 0; 
} 

hatte, musste ich durch die Schaffung einer Spezialisierung der str_length eine „Obergrenze“ von 500 einzustellen. Wenn ich das ausschließe, würde dies dazu führen, dass mein Compiler auf unbestimmte Zeit läuft (vermutlich mit unendlichen Spezialisierungen von str_length).

Gibt es etwas, was ich tun könnte, um den Index = 500 zu begrenzen? Ich verwende VC++ 2015, wenn das hilft.

Oh, und ich verwende nicht constexpr, weil VC++ die C++ 14 erweiterten conexpr Funktionen noch nicht ganz unterstützt. (https://msdn.microsoft.com/en-us/library/hh567368.aspx#cpp14table)

+0

Warum verwenden Sie nicht die Tatsache, dass 'bitarr' ein * Array * ist und daher bereits eine Größe für die Kompilierung hat? –

+0

Wie gesagt, nur mit TMP rumspielen. – lennoxho

Antwort

0

Der übliche Weg, unendliche Template Instanziierung in diesen Situationen zu stoppen, ist durch Spezialisierung; Das ist orthogonal zu constexpr -ness von irgendetwas. Überprüfung der Liste der zusätzlichen Sachen, die erweitert constexpr ermöglicht in C++ 14, sehe ich nichts in dem folgenden Beispiel, das erweiterte constexpr Unterstützung benötigt. 6.1.1 gcc kompiliert diese in -std=c++11 Compliance-Modus, FWIW:

#include <iostream> 

template<const char *str, size_t index, char c> class str_length_helper; 

template <const char *str> 
class str_length { 
public: 

    static constexpr std::size_t val() 
    { 
     return str_length_helper<str, 0, str[0]>::val(); 
    } 
}; 

template<const char *str, std::size_t index, char c> 
class str_length_helper { 

public: 

    static constexpr std::size_t val() 
    { 
     return 1+str_length_helper<str, index+1, str[index+1]>::val(); 
    } 
}; 

template<const char *str, std::size_t index> 
class str_length_helper<str, index, 0> { 
public: 

    static constexpr std::size_t val() 
    { 
     return 0; 
    } 
}; 

static constexpr char bitarr[] { "0000000000000000000" }; 

int main() { 
    std::cout << str_length<bitarr>::val() << std::endl; 

    getchar(); 
    return 0; 
} 

Beachten Sie jedoch, dass die Zeichenfolge selbst constexpr sein muss. Wie die Kommentare feststellten, ist dies von zweifelhaftem praktischen Nutzen; Aber es ist nichts falsch daran, auf diese Art und Weise herumzuspielen, um mit der Metaprogrammierung Schritt zu halten.

Der Schlüsselpunkt ist die Verwendung der Spezialisierung, und die Tatsache, dass str[index] als Vorlagenparameter strconstexpr sein muss.

+0

Danke für die schnelle Antwort. Leider scheint das auf VC++ 2015 nicht zu funktionieren. Erhalten Sie diesen Fehler (https://msdn.microsoft.com/en-us/library/fhfd9502.aspx) – lennoxho

+0

Nun, es sieht so aus, als ob Ihr Compiler keine volle C++ 11 Unterstützung hat. –