2013-09-24 35 views
7

Poszukuję sposobu sprawdzenia argumentów funkcji w czasie kompilacji, jeśli można to zrobić dla kompilatora.C++ argumenty funkcji sprawdzania kompilacji w czasie

Aby być bardziej szczegółowym: załóżmy, że mamy jakąś klasę Matrix.

class Matrix 
{ 
    int x_size; 
    int y_size; 

public: 
    Matrix(int width, int height): 
     x_size{width}, 
     y_size{height} 
    {} 
    Matrix(): 
     Matrix(0, 0) 
    {} 
}; 

int main() 
{ 
    Matrix a; // good. 
    Matrix b(1, 10); // good. 
    Matrix c(0, 4); // bad, I want compilation error here. 
} 

Więc mogę sprawdzić czy różnicują zachowania (przeciążenia funkcja?) W przypadku statycznych (źródło kodowane) wartości przekazywane do funkcji?

Jeśli wartość nie jest statyczna:

std::cin >> size; 
Matrix d(size, size); 

jesteśmy tylko w stanie zrobić kontrole uruchomieniowe. Ale jeśli wartości są zakodowane w źródle? Czy mogę w tym przypadku wykonać kontrolę kompilacji?

EDYCJA: Myślę, że to może być możliwe z constexpr constructor, ale w każdym razie przeciążanie zi bez constexpr jest niedozwolone. Więc problem nie może być rozwiązany w sposób, jak przypuszczam.

+0

Nie sądzę, że można złamać kompilację, jeśli ktoś przekaże błędne argumenty. Normalnym sposobem jest wyrzucenie wyjątku na złe wartości –

Odpowiedz

4

Aby uzyskać błąd czasu kompilacji musisz szablon:

template <int width, int height> 
class MatrixTemplate : public Matrix 
{ 
    static_assert(0 < width, "Invalid Width"); 
    static_assert(0 < height, "Invalid Height"); 
    public: 
    MatrixTemplate() 
    : Matrix(width, height) 
    {} 
}; 

(Btw .: Proponuję niepodpisanych typów na indeksy)

Jeśli nie masz static_assert (tu mogę przełączyć na unsigned):

template <unsigned width, unsigned height> 
class MatrixTemplate : public Matrix 
{ 
    public: 
    MatrixTemplate() 
    : Matrix(width, height) 
    {} 
}; 

template <> class MatrixTemplate<0, 0> {}; 
template <unsigned height> class MatrixTemplate<0, height> {}; 
template <unsigned width> class MatrixTemplate<width, 0> {}; 

nie ma wsparcia dla pustych matrycach (MatrixTemplate < 0, 0>), tutaj. Ale powinno być łatwe zadanie dostosowania static_asserts lub klasy MatrixTemplate < 0. 0>.

+0

To jest szczeniak! Właśnie chciałem to zakodować. Mieć uprowadzenie.Możesz to również zrobić za pomocą 'constexpr', ale pewien kompilator nie obsługuje go ;-( – Bathsheba

+1

Myślę o tym, ale zakładam, że rozmiary matrycy nie są stałe dla życia obiektu Matrix. nie ma zastosowania w moim przypadku: –

+0

W twoim kodzie występuje literówka: 'static_assert <' zamiast 'static_assert ('. – Lumen

1

Sposób, że liniowy pakiety algebry mają tendencję do zrobienia tego jest użycie szablonów dla macierzy o stałym rozmiarze, jak w:

template<int x, int y> class Matrix { ... }

i dodatkową klasę dla matryc, które mogą zmienić rozmiar w czasie wykonywania

class DynamicMatrix {...}

Nadal trzeba polegać na programatorze używającym pierwszej opcji, gdy chcą mieć matryce o stałym rozmiarze, ale wersja szablonu ułatwia wygenerowanie co błąd mpilera, gdy x lub y wynosi zero.

0

Run-time:

Matrix(int width, int height): 
    x_size{width}, 
    y_size{height} 
{ 
     assert(x_size>0); 
     assert(y_size>0); 
} 

czasie kompilacji (Faktycznie nie można było zrobić to z argumentów funkcji można użyć sposobów szablonów.):

template <size_t WIDTH, size_t HEIGHT> 
class Matrix 
{ 
    const size_t x_size = WIDTH; 
    const size_t y_size = HEIGHT; 

    static_assert(WIDTH > 0, "Width must > 0"); 
    static_assert(HEIGHT > 0, "Height must > 0"); 
}; 
2

Możesz dodać metodę jak to:

template <int WIDTH, int HEIGHT> 
Matrix CreateMatrix() 
{ 
    static_assert(WIDTH > 0, "WIDTH > 0 failed"); 
    static_assert(HEIGHT > 0, "HEIGHT > 0 failed"); 

    return Matrix(WIDTH, HEIGHT); 
} 

int main() { 
    Matrix m(0, 2);  // no static check 
    Matrix m2 = CreateMatrix<0,2>(); // static check 

    return 0; 
} 
+1

Dobry pomysł. Można sprawić, by metoda "CreateMatrix" była fabryczną funkcją składową "Matrixa" i uczyniła konstruktory prywatnymi. Następnie każda zewnętrzna konstrukcja jest sprawdzana statycznie (jeśli jest to pożądane). – Lumen

Powiązane problemy