2013-07-23 10 views
10

In einem Vorstellungsgespräch wurde ich gebeten, eine Metafunktion zu schreiben, die bestimmt, ob ein Typ ein Zeiger war. Das ist, was ich vorgestellt:Wie kann ich kompilieren Zeit Zusicherungen ohne C++ 11

template <typename T> 
struct is_pointer 
{ static const bool value = false; } 

template <typename T> 
struct is_pointer<T *> 
{ static const bool value = true; } 

Dann wurde ich gebeten, eine Meta-Assertion zu schreiben, die während der Kompilierung fehl, wenn meine is_pointer Funktion nicht ist das Richtige zu tun.

Als ich static_assert verwendete, sagte er mir explizit, dass ich nur C++ 98 Standard verwenden darf. Wie kann ich das erreichen?

assert<!is_pointer<char>::value>();  // valid 
assert<is_pointer<char *>::value>(); // valid 

assert<is_pointer<char>::value>();  // compilation error: 
             // use of incomplete class 
+8

ich an dieser Stelle denken Sie die „Prüfung bestanden um zu sehen, ob Sie tatsächlich die Sprache "Teil des Interviews kennen, es sei denn, das Unternehmen macht C++ - Compiler oder so etwas. –

Antwort

5

In Ihrem Fall

template <bool> struct assert; 
template <> struct assert<true> {}; 

würde das Problem gelöst haben kann in fast jedem Kontext verwendet werden und löst den Compiler aus, wenn die Bedingung false ist, da es versuchen würde, a zu schreiben n ungültiger Typ (Array mit negativer Anzahl von Elementen). Es kann in verschiedenen Kontexten verwendet werden:

// namespace level: 
static_assert(sizeof(int)==4); 
struct type { 
    // class level: 
    static_assert(sizeof(int)==4); 
    void f() { 
     // function level 
     static_assert(sizeof(int)==4); 
    } 
}; 
+0

Das ist nicht das, was SFINAE ist (die Lösung ist in Ordnung, aber der Name wird missbraucht). –

+0

Dies ist auch auf Orte beschränkt, an denen Sie ein Objekt des Typs erstellen können. Um es in anderen Kontexten verwenden zu können, müssten Sie gefälschte Objekte erstellen: '// Namespace: assert myassert;' –

9

Es gibt verschiedene Ansätze, ein allgemeines einen ungültigen Typ typedef versuchen: Diese

#define static_assert(condition) \ 
     typedef char assert ## __LINE__ [((condition)?1:-1)] 

+3

Dieser kann sogar in reinem C verwendet werden :) Beachten Sie jedoch, dass mit Ihrem aktuellen Makro der typedef immer bleibt sei 'assert__LINE__', wie es ist; Um '__LINE__' auf die tatsächliche Zeilennummer zu erweitern, benötigen Sie einen dazwischen liegenden" Join "-Macro-Aufruf: [Was sollte mit Makros geschehen, die zwei Token zusammenfügen müssen?] (http://www.parashift.com/c++faq) /macros-mit-toke-pasting.html) –

3

ich BOOST_STATIC_ASSERT verwenden würde. Sie können den Code ansehen: boost/static_assert.hpp.

Hier ist eine sehr vereinfachte Version, nur um Ihnen eine Vorstellung zu geben:

#define JOIN(X, Y) DO_JOIN(X, Y) 
#define DO_JOIN(X, Y) X ## Y 

template<bool cond> 
struct Static_assert_helper; // incomplete type 

template<> 
struct Static_assert_helper<true> { 
    typedef int Type; 
}; 

#define STATIC_ASSERT(cond) \ 
    typedef Static_assert_helper<(cond)>::Type JOIN(Static_assert_typedef_, __LINE__) 

Es kann in vielen Orten verwendet werden (in der Dokumentation siehe Beispiele).

(Boost-Implementierung ist vollständiger, mit zB einem sizeof und eine Zwischen Struktur, eine bessere Fehlermeldung zu geben und auf eine breite Palette von Compilern tragbar sein.)

Verwandte Themen