---
tags: c++, c++11
---
[](https://hackmd.io/kfOxqe-JRs6xihKRzIUjBQ)
# 如何寫出不會被誤用的code #2
```cpp=
class Rectangle {
public:
Rectangle(unsigned int w, unsigned int h)
: width(w), height(h) {
}
private:
unsigned int width;
unsigned int height;
};
```
一個常見的矩形class,長和寬是unsighed int,看起來很美好。caller可以這樣寫,完全沒問題。
```cpp
Rectangle(100, 200);
```
## 兩個問題
1. width和height寫反也合法,上一集有講解,不多贅述
3. 引數是負數也完全合法
```cpp
Rectangle(-100, -200);
```
## 將width和height變成新的type再加上explicit呢?
利用上一集寫過的例子來改,會變這樣
```cpp=
class Width {
public:
explicit Width(unsigned int w)
: width(w) {
}
private:
unsigned int width;
};
class Height {
public:
explicit Height(unsigned int h)
: height(h) {
}
private:
unsigned int height;
};
class Rectangle {
public:
Rectangle(const Width &w, const Height &h)
: width(w), height(h) {
}
private:
Width width;
Height height;
};
```
現在解決了第一個問題,至少width和height的順序固定了。
但第二個問題沒有解決,將負數assign給unsigned int是合法的,width和height會變成一個很大的正整數,通常我們不會希望這樣的結果。
## 利用type traits來檢查
type traits提供了一系列型別檢查用的template,其中一個std::unsigned剛好可以派上用場。
改寫一下上面的code:
```cpp=
template <typename T>
class Width {
public:
explicit Width(T w)
: width(w) {
static_assert(std::is_unsigned_v<T>, "signed types is not allow.");
}
private:
T width;
};
template <typename T>
class Height {
public:
explicit Height(T h)
: height(h) {
static_assert(std::is_unsigned_v<T>, "signed types is not allow.");
}
private:
T height;
};
template <typename T1, typename T2>
class Rectangle {
public:
Rectangle(const Width<T1> &w, const Height<T2> &h)
: width(w), height(h) {
}
private:
Width<T1> width;
Height<T2> height;
};
```
現在caller只能用unsigned types來宣告width和height了
```cpp
Rectangle(Width(100u), Height(200u)); // 注意要加上unsigned-suffix 'u'
```
(待續)