Giriş
Şu satırı dahil
ederiz.
#include <boost/serialization/strong_typedef.hpp>
Bu macro niçin serialization altında bilmiyorum. Amacı
mevcut bir tipten yepyeni bir tip tanımlayabilmek. Bu yepyeni tip, metod parametrelerinde kullanılarak daha type safe bir kod elde ediliyor.
1. Rust Dili
Benzer bir özellik Rust programlama dilinde var. O da bu özelliği Haskell'den almış
deniliyor.
Örnek
Rust dilinde şöyle
yaparız. old_enough() metodu sadece Years tipi ile çağrılabilir. i64 olan bir başka parametre ile
çağrılamaz.
struct Days(i64);
struct Years(i64);
fn old_enough(age: &Years) -> bool {
age.0 >= 18
}
2. typdef Kelimesi Farklı Tipler Yaratmak İçin Yetersizdir
Örnek
İşe yaramadığını görmek için şöyle yaparız. Elimizde şöyle bir kod
olsun.
typedef int TA;
typedef int TB;
std::variant<TA, TB> a(TA(1));
Bu kod içinde TA ve TB isminde iki farklı tip yaratılıyor gibi görünse de derleyici bunları farklı şeyler olarak düşünmeyebilir. Bu yüzden
BOOST_STRONG_TYPEDEF kullanımına ihtiyacımız var.
3. using Kelimesi Farklı Tipler Yaratmak İçin Yetersizdir
Örnek
İşe yaramadığını görmek için şöyle
yaparız
typedef int Days;
using Years = int;
bool old_enough(Years age) {
return age >= 18;
}
4. Alternatif Çözümler
Eğer elimizdeki tip primitive ise
enum kullanılabilir. Ancak primitive değilse bu çözüm işe yaramaz.
Örnek
Şöyle
yaparız
enum class Days : int {};
enum class Years : int {};
bool old_enough(Years age) {
return static_cast<int>(age) >= 18;
}
5. Eğer Kendimiz Gerçekleştirmek İstersek
Açıklaması
şöyle. Template sınıfın ilk parametresini Tag yaparız.
...another common approach is making(/expanding) the Number class (template) a class template parameterized over type template tag parameter, such that specializations over the tag types results in strong typing.
Örnek
Şöyle
yaparız.
template<typename Tag, typename ValueType = int>
struct Number {
ValueType value;
// ... common number functionality.
};
using YearNumber = Number<struct NumberTag>;
using DayNumber = Number<struct DayTag>;
void takeYears(const YearNumber&) {}
void takeDays(const DayNumber&) {}
int main() {
YearNumber y{2020};
DayNumber d{5};
takeYears(y);
//takeDays(y); // error: candidate function not viable
takeDays(d);
//takeYears(d); // error: candidate function not viable
return 0;
}
6. BOOST_STRONG_TYPEDEF Kullanımı
Ve nihayet bu macronun kullanımına bakalım.
Örnek
Şöyle
yaparız. TIMER_ID ve PROCESS_ID string olmalarına rağmen == kodu derleme hatası verir.
BOOST_STRONG_TYPEDEF(std::string, TIMER_ID)
BOOST_STRONG_TYPEDEF(std::string, PROCESS_ID)
int main()
{
TIMER_ID t_id("Timer");
PROCESS_ID p_id("Process");
if (t_id == p_id)
std::cout << "They are equal!" << std::endl;
}
Örnek
Şöyle
yaparız.
BOOST_STRONG_TYPEDEF(int, X)
BOOST_STRONG_TYPEDEF(int, Y)
BOOST_STRONG_TYPEDEF(int, Width)
BOOST_STRONG_TYPEDEF(int, Height)
struct Rect {
Rect(X x, Y y, Width w, Height h);
};
// Usage:
Rect rect(X(10), Y(20), Width(800), Height(600));
Örnek
Elimizde şöyle bir typedef
olsun
BOOST_STRONG_TYPEDEF(std::string, MY_ID)
Şöyle
yaparız.
std::vector<std::string> id_vec = ...;
std::set<MY_ID> ids;
for (auto const & id : id_vec)
{
ids.insert(MY_ID{id});
}