У світі веб-розробки простота та ефективність — це ключові фактори. Однак, в порівнянні з шаблонами в C++, Generics в Go та TypeScript працюють дещо по-іншому. Хоча вони всі забезпечують спосіб написання багаторазового та безпечного коду, механізми та філософія реалізації відрізняються.
1. Шаблони в C++
Генерація коду на етапі компіляції: Шаблони C++ — це форма метапрограмування на етапі компіляції. Коли ви використовуєте шаблон із певним типом, компілятор генерує окрему версію коду для цього типу.
Тьюрінг-повна: Шаблони в C++ можуть використовуватися для складних обчислень на етапі компіляції, таких як SFINAE (Substitution Failure Is Not An Error), спеціалізація та перевантаження.
Компроміс у продуктивності: Оскільки кожна інстанціація створює нову версію коду, це може призвести до збільшення розміру коду.
Приклад:
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int result = add(5, 10); // Ініціалізація шаблону add
double dresult = add(5.5, 2.2); // Ініціалізація шаблону add
}
2. Generics у Go (з версії Go 1.18)
Типові параметри з обмеженнями: Go generics вводять параметри типу з обмеженнями, які визначаються через інтерфейси.
Підхід з «стертих типів»: На відміну від шаблонів у C++, Generics в Go реалізуються за допомогою стертих типів на етапі виконання. Компилятор генерує одну версію коду, використовуючи рефлексію або інтерфейси, коли це необхідно.
Простота та обмеження: Go generics навмисно зроблені простими, щоб уникнути складнощів та накладних витрат на компіляцію.
Приклад:
func Add[T int | float64](a, b T) T {
return a + b
}
func main() {
fmt.Println(Add(3, 4))
fmt.Println(Add(3.5, 2.2))
}
3. Generics у TypeScript
Стертий тип на етапі виконання: Generics в TypeScript існують тільки на етапі компіляції та не впливають на згенерований JavaScript код.
Гнучкість та динамічність: Оскільки TypeScript є надмножиною JavaScript, його generics більш гнучкі, зосереджені на забезпеченні безпеки типів під час розробки без виконання цього на етапі виконання.
Немає накладних витрат на продуктивність: Оскільки generics зникають у згенерованому JavaScript, немає накладних витрат на виконання.
Приклад:
function identity<T>(arg: T): T {
return arg;
}
console.log(identity(42));
console.log(identity("Hello"));
Основні відмінності
Заключні зауваження
Якщо ви приходите з C++, Go і TypeScript generics можуть здаватися менш потужними, оскільки вони не створюють спеціалізований код для кожного типу, а натомість покладаються на абстракцію.
Go націлений на простоту та підтримуваність з мінімальними витратами на виконання.
Generics у TypeScript надають статичну безпеку типів без впливу на поведінку під час виконання.
Кожен підхід адаптований до цілей відповідної мови, що пріоритетно обирає або продуктивність (C++), простоту (Go) або досвід розробника (TypeScript).
Перекладено з: What are the differences between templates in C++ and generics in Go and TypeScript?