2017-09-19 1 views
0

Ich brauche eine Möglichkeit zu validieren, dass eine konstante Zeichenfolge ein bestimmtes Zeichen zum Zeitpunkt der Kompilierung enthält. Ich dachte über die Verwendung von static_assert, aber traf eine Ziegelmauer, weil ich versuchte, mit der .find-Methode, die nicht konstant ist.Gibt es kreative Möglichkeiten, um zu überprüfen, ob eine Zeichenfolge zum Zeitpunkt der Kompilierung oder vor ihrer Verwendung ein verbotenes Zeichen enthält?

Ich habe eine Option, die Überprüfung im Konstruktor der Klasse (Instanzen sind static const Mitglieder der genannten Klasse).
Aber bevor ich das Bullet beiße (da die Änderung des Konstruktorverhaltens andere Implikationen hat), würde ich gerne sehen, ob irgendjemand sonst eine dieser kreativen Out-of-the-Box-Ideen hat, um dies noch zu erledigen, vorzugsweise zur Kompilierzeit .

+1

Sie können die Funktion constexpr aus C-Literal String verwenden. Gcc hat auch eine Extension, so dass udl auf eine Literal-Zeichenfolge erlaubt ist. – Jarod42

+0

Spot auf! Ich habe es geschafft, es zum Laufen zu bringen. Obwohl ich denke, @AndyG Antwort ist besser lesbar (Kennzeichnung als Antwort, um anderen zu helfen), das ist, was ich geschafft habe, mit Ihrem Vorschlag fertig zu werden: –

Antwort

4

von konstantem String vielleicht meinen Sie einen Stringliteral, für std::string nicht in einem konstanten Ausdruck verwendet werden kann.

Im Stringliteral Fall nutzen wir constexpr nehmen kann: (Live Demo)

template<int N> 
constexpr bool has_forbidden_char(const char (&str) [N], char forbidden) 
{ 
    for(int i = 0; i < N; ++i) 
    { 
     if (str[i] == forbidden) 
      return true; 
    } 
    return false; 
} 

int main() 
{ 
    static_assert(!has_forbidden_char("foobar", 'x')); 
    static_assert(has_forbidden_char("foobar", 'f')); 
} 

Edit: Iterierte zu N-1, wenn Sie Sie davon ausgehen, nur Stringliterale und nicht willkürlich Zeichen-Arrays erhalten . Auf diese Weise werden Sie das NULL-Zeichen '\ 0' nicht jedes Mal überprüfen. (Null-Länge-Arrays existiert nicht in C++, also keine Sorge um die Indizierung bei -1)

//... 
for(int i = 0; i < N-1; ++i){ //... 

Edit2: Da Sie Visual Studio 2015 verwenden, die nicht entspannt constexpr hat Funktionalität, hier ist eine C++ 11 konforme Lösung, die funktioniert:

namespace detail { 
    template<int N> 
    constexpr bool has_forbidden_char_help(const char(&str)[N], char forbidden, int index) 
    { 
     return (index < N && (str[index] == forbidden || has_forbidden_char_help(str, forbidden, index+1))); 
    } 
} // namespace detail 

template<int N> 
constexpr bool has_forbidden_char(const char (&str) [N], char forbidden) 
{ 
    return detail::has_forbidden_char_help(str, forbidden, 0); 
} 

int main() 
{ 
    static_assert(!has_forbidden_char("foobar", 'x'), "foobar doesn't have x, so this shouldn't fail..."); 
    static_assert(has_forbidden_char("foobar", 'f'), "foobar does have f, so this shouldn't fail..."); 
} 
+0

Danke für das detaillierte Beispiel, @AndyG. Leider mochte mein Compiler (VS2015) viele der von Ihnen verwendeten Konstrukte nicht und das Umschalten des Compilers ist keine Option. –

+0

@SeeSharper: Gib mir eine Minute und ich werde eine VS2015 konforme Version machen. – AndyG

+0

@SeeSharper: Siehe die bearbeitete Antwort :-) – AndyG

Verwandte Themen