2014-12-12 3 views
6

Ich kann ein Compile-Time-Intervall-Checker nicht finden, also habe ich einige Ansätze versucht, eine eigene zu entwickeln, wo Sie den Wert in Frage, den minimalen Wert und den maximalen Wert eingeben sollten, so dass der Checker würde true zurückgeben, wenn der fragliche Wert zwischen den beiden Endpunkten liegt.Kompilieren Zeitintervall Checker

Mein erster Ansatz war nur in der Lage sein ints zu vergleichen und es sah wie folgt aus:

template<int Val, int LoEnd, int HiEnd> 
struct is_in_interval : public std::integral_constant<bool, Val >= LoEnd && Val <= HiEnd>::type 
{}; 

Ein Aufruf der Funktion wie

bool inside = is_in_interval<3, 1, 10>::value; 

aussehen würde und das schien zu arbeiten. Ich kann es selbst bei der Kompilierung macht fehlschlagen, wenn das untere Ende höher war als das obere Ende:

template<int val, int LoEnd, int HiEnd> 
struct is_in_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
{}; 

zu können kam jeden Wert vergleichen ich mit diesem nach oben:

template<typename T> 
struct is_in 
{ 
    template<T val, T LoEnd, T HiEnd> 
    struct closed_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
    {}; 
}; 

Jetzt, jedoch wurden die Anrufe Unbekannter:

bool inside = is_in<int>::closed_interval<3,1,10>::value; 

aber ich hatte immer noch die Fähigkeit enable_if zu verwenden und könnten sogar hinzufügen mehr (für is_integral zum Beispiel zu überprüfen).

Meine Frage ist, ob es irgendwie möglich ist, diese verallgemeinerte Version leichter aufzurufen, wahrscheinlich indem man den Typ (int) vom Nicht-Typ (3,1,1,10) herleitet?

Auf Nebenbei konnte ich verwenden:

template<typename T> 
constexpr bool isInInterval3(T val, T LoEnd, T HiEnd) 
{ 
    return val >= LoEnd && val <= HiEnd; 
} 

aber in dieser Funktion Ich glaube nicht, dass ich das std::enable_if Typen Merkmal, dass LoEnd <= HiEnd behaupten kann.

+0

Sie noch 'isInInterval3' verwenden können, einen Compiler-Check zu machen:' constexpr Bool assert_isIn (T const val, T const min, T const max) {return val> = min && val <= max? wahr: Wurf "außerhalb des Bereichs"; } 'Wenn Sie eine solche Funktion in einem Kontext verwenden, in dem anstelle einer Ausnahme ein konstanter Ausdruck erforderlich ist, erhalten Sie einen Fehler bei der Kompilierung. Aber das ist nicht sehr nützlich; Ich würde lieber 'static_assert (isInInterval3 (val, lo, hi)," !! ");' mit Ihrer aktuellen Definition verwenden. – dyp

+0

@dyp Weder SFINAE-freundlich noch eine schöne und elegante Art, es zu beenden? – Columbo

+0

@Columbo Als grundlegender Baustein finde ich das 'isInterval3' des OP nützlich. Sie können sowohl SFINAE als auch einen schweren Fehler erstellen. Wie gesagt, ich denke, mein 'assert_isIn' ist nicht sehr nützlich. – dyp

Antwort

0

können Sie geben sowohl ‚Typname T‘ und andere Parameter in einer Vorlage:

template<typename T, T val, T LoEnd, T HiEnd> 
struct is_in_interval : public std::integral_constant< 
typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
{}; 

Dann können Sie ein Makro in_interval mit nur val, LoEnd und HiEnd Parameter definieren, die is_in_interval mit dem ersten Template-Parameter nennen zum Beispiel decltype(val):

#define in_interval(val, LoEnd, HiEnd) (is_in_interval<decltype(val), val, LoEnd, HiEnd>::value) 

Und Sie können es verwenden, wie folgt:

cout << in_interval(3, 1, 10) << endl; 

Dies alles funktioniert auf meinem VS2012