Pull to refresh

Comments 16

Всё-таки иногда не хватает мощности констрейнтов генериков в сишарпе, хотелось бы на Enum (хотя clr поддерживает такое), Числа, операции +\- и т.д.
Вы не правильно поняли контекст предложения, более того — официальный русский перевод слова genericsУниверсальные шаблоны

А насчет, того что generics != templates, то шаблоны в C++ — это макросы, «выглядящие» как классы, а generics — это параметричесике типы.
Не нашёл выше по ссылке
официальный русский перевод слова generics

Зато указанная статья встречает плашкой:
Данная статья переведена автоматически. Наведите указатель мыши на предложения статьи, чтобы просмотреть исходный текст. Дополнительные сведения.

Да и дилетантский способ проверить популярность того или иного термина показывает:
c# обобщения — 222 тыс. результатов;
c# универсальные шаблоны — 6,5 тыс. результатов.
Я не стал бы использовать термин «универсальный шаблон» как минимум потому, что у нас шаблоны уже есть, это templates. А как автор правильно сказал, generics ≠ templates. Поэтому generics, мне кажется, лучше всё-таки называть «обобщениями» или же «параметризованными типами».
Шаблоны в С++ — это не макросы. Хотя бы потому, что они реализуют полный по тьюрингу чистый функциональный язык оперирующий с типами.
ну это ни в коем случае не доказывает обратное.

более того, я писал:

>>это макросы, «выглядящие» как классы

какую абстракцию иметь ввиду, дело другое
Если бы это были макросы, то шаблоны можно было бы «раскрыть» преобразовав программу к семантически эквивалентному виду, но без макросов. Однако в общем случае это невозможно, потому что в С++ есть SFINAE.

Например, у вас никак не получится реализовать на макросах вот такой код:
#include <type_traits>
#include <iostream>
#include <string>
 
struct NonPod { virtual ~NonPod() {} };
struct Pod {};
 
struct classifier
{
    template<class T> 
    static std::string classify(&&rr, ...) 
    { 
        return "Classified as non POD"; 
    }
 
    template<class T>
    static std::string classify(&&rr, typename std::enable_if<std::is_pod<T>::value>::type * = 0) 
    { 
        return "Classified as POD"; 
    }
};
 
void main()
{
    std::cout << classifier::classify(NonPod()) << std::endl; // prints "Classified as non POD"
    std::cout << classifier::classify(Pod()) << std::endl; // prints "Classified as POD"
}

Вы просто не сможете определить какую перегрузку выбрать, т.к. используя только макросы вы не сможете определить, является ли тип Т pod-типом — для этого нужен полноценный компилятор. И это только частный случай :)
Я что-то не понял зачем в Double Dispatch примере интерфейсы, ведь через них пользоваться этим кодом не получится. Может я чего-то не понимаю…
интерфейсы лишь заменяют базовый класс Thing как в примере с Multiple dispatch. не более чем абстракция.
В данном случае, они по-моему только мешают, потому что если переписать main вот так:
ICollidable asteroid = new Asteroid(); ICollidable spaceship = new Spaceship();
Что просится глядя на определения классов, код становится не рабочим.
согласен, stackoverflow — не самый приятный момент, однако решением данного случая является именно multiple dispatch.

но это при условии, что используется одна иерархия классов. при введении, скажем, AsteroidBase и SpaceshipBase и без интерфейса, тогда все станет на свои места.
А есть конкретный пример системы, где это можно было бы применить?
например, при работе с указателями:

interface IReader<T>
{
    unsafe T Read(void* ptr, int index);
}

именно здесь не обошлось бы без явной имплементации интерфейса и не надо будет в коде вводить if/else, либо switch для типов аргументов.
LINQ целиком и полностью основан на дженериках.
Sign up to leave a comment.

Articles