Рубрики
Без рубрики

Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – шаблоны

Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java. Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java, кроме самого старого… С тегами cpp, новички, java, template.re.

Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java, кроме самого старого… С тегами cpp, новички, java, template.re. С Java на C++ (Серия из 2 частей) С Java на C++ – шаблоны

Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java, кроме самого старого… С тегами cpp, новички, java, template.re. От Java до C++ (серия из 2 частей) Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java. Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java, кроме самого старого… С тегами cpp, новички, java, template.re. От Java до C++ (серия из 2 частей) Java до C++ – шаблоны Универсальное программирование – это повседневный хлеб, возможно, для каждого, но самые старые программисты Java все еще помнят времена, когда мы бросали вещи повсюду, и списки создавались без явного указания компилятору, какой тип объектов они содержат. ава программист где-то там. Твиттер || Facebook || Instagram || Средний или просто напишите мне по адресу || jayviveki13@gmail.com От Java до C++ – универсальное программирование шаблонов – это повседневный хлеб, возможно, для каждого программиста Java, кроме самого старого… С тегами cpp, новички, java, template.re. От от Java до C++ (серия из 2 частей) Java до C++ – шаблоны Универсальное программирование – это повседневный хлеб, возможно, для каждого, только самые старые программисты Java все еще помнят, что не должно удивлять, что та же функциональность существует в старшем двоюродном брате Java – C++. были времена, когда мы бросали вещи повсюду, и списки создавались без явного указания компилятору, какой тип объектов они содержат. ава программист где-то там.

Твиттер Facebook

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ 2! Я не хотел начинать здесь полномасштабный урок истории. Я использую новейший стандарт C++20, и все примеры компилируются и работают в нем. Я могу время от времени указывать, когда была введена определенная функциональность.

Пойдем

Универсальное программирование на C++ строго связано с концепцией шаблона . Хотя в мире Java мы привыкли к идее дженериков , шаблоны в C++ немного отличаются и, на мой взгляд, сложнее для понимания. В этой статье я постараюсь сделать все возможное, чтобы представить универсальное программирование на C++ таким образом, чтобы каждый программист Java мог легко понять. Давайте начнем с определения шаблона , данного Страуструп сам.

По сути, шаблон – это механизм, который позволяет программисту использовать типы в качестве параметров для класса или функции. Затем компилятор генерирует определенный класс или функцию, когда мы позже предоставляем определенные типы в качестве аргументов.

Мы можем выбрать три отдельных типа шаблонов :

  • шаблоны функций
  • шаблоны классов
  • шаблоны переменных (начиная с C++14)

Дополнительная типология поставляется с параметрами шаблона |, оцененными во время компиляции), другими словами, что может быть передано в качестве параметра в шаблон ключевое слово:

  • типы параметров – наиболее распространенные, например. шаблон<имя типа|класс T>

  • нет -параметры типа – обычно уже заданное значение, например, число 6. Начиная с C++20, также возможно использовать числа с плавающей запятой и строки (массивы) в стиле C, хотя и с некоторыми ограничениями. Однако здесь можно использовать множество других типов в качестве перечислений, указателей всех видов или std::nullptr_t

  • шаблон-параметры шаблона – когда мы вводим шаблон в другой шаблон

Здесь мы должны помнить, что значение T имеет свою собственную область действия, ограниченную только шаблоном !

Шаблоны функций

Этот тип шаблонов должен быть хорошо знаком каждому программисту Java, так как они выглядят и работают так же, как дженерики в Java. Мы передаем функции некоторый универсальный класс/тип без каких-либо дополнительных предположений.

#include 
using namespace std;


template   // T is usually used to indicate first param, U to indicate second one
T myMax(T x, T y)
{
    return (x > y) ? x: y;
}

// Based on the calls to this function in the main() method
// the template will be replaced with three separate
// implementations of the above method using ints, doubles and    // chars as input params.

int main()
{
    short myShort = 2;
    cout << myMax(3, 7) << endl; // Call myMax for int
    cout << myMax(myShort, 7) << endl; // ERROR - this won't compile as the params are not of the same type 
    cout << myMax(3.0, 7.0) << endl; // call myMax for double
    cout << myMax('g', 'e') << endl; // call myMax for char

    return 0;
}

Первое, с чего нужно начать, – выше шаблон – это просто рецепт для создания конкретных определений функций . Процесс этого создания называется создание экземпляра шаблона .

Второе, что нужно обсудить, это следует ли нам использовать имя типа или класс или класс в определении шаблона . или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). или

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были вызваны, Подробнее об этом можно найти здесь

или класс в определении шаблона

template
void PrintNumbers(const T1& t1Data, const T2& t2Data)
{}

// This
PrintNumbers(10, 100);    // int, int
PrintNumbers(14, 14.5);   // int, double
PrintNumbers(59.66, 150); // double, int

// Can be changed to use this - and therefore limiting
// the generated specialized versions to only double one
PrintNumbers(10, 100);    // int, int
PrintNumbers(14, 14.5);   // int, double
PrintNumbers(59.66, 150); // double, int

// Generated specialised version
void PrintNumbers(const double& t1Data, const T2& t2Data)
{}

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были вызваны, Подробнее об этом || можно найти здесь || . я. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, использовать || явный шаблон – это фактическая подсказка компилятору, какой будет тип этого метода также следует использовать, когда нет способа определить используемый тип из параметров конструктора или методов. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тот же типаж, и все тут. тарелки или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были вызваны, Подробнее об этом || можно найти здесь || . я. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, использовать || явный шаблон – это фактическая подсказка компилятору, каким будет тип этого метода. Также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или Рассмотрите этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тот же типаж, и все тут. тарелки

template
void PrintSize()
{
    cout << "Size of this type:" << sizeof(T);
}

// Calling it like this will cause compiler error
PrintSize();

// But with this - it's working
PrintSize();

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов

или класс в определении шаблона

#include 
using namespace std;


template 
T myMax(T x, T y)
{
    cout << "Inside template implementation: ";
    return (x > y) ? x: y;
}

template<>
short myMax(short x, short y)
{
    cout << "Inside short implementation: ";
    return (x > y) ? x: y;
}

int main()
{
    cout << myMax((short)3, (short)7 ) << "\n" << endl; // Call myMax for short
    cout << myMax(3, 7) << "\n" << endl; // Call myMax for int
    cout << myMax(3.0, 7.0) << "\n" << endl; // call myMax for double
    cout << myMax('g', 'e') << "\n" << endl; // call myMax for char

    return 0;
}

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. явное преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение – использовать || явный шаблон. Это фактический намек компилятору, каким будет тип. Этот метод также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или что в конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, использовать || явный шаблон – это фактическая подсказка компилятору, какой будет тип этого метода также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

template
class A  {
    public:
        T x;
        U y;
        A() {   cout<<"Constructor Called"< a;  // This will call A
    return 0;
}

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, использовать || явный шаблон – это фактическая подсказка компилятору, каким будет тип этого метода также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или Вывод будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

Constructor Called

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. явное преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение – использовать || явный шаблон. Это фактический намек компилятору, каким будет тип. Этот метод также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или шаблонов классов. Вывод будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что

#include
using namespace std;


template 
class MyClass
{
public:
    MyClass(T x, T y)
    {
        cout << "My class constructor: " + to_string(x) + " " + to_string(y) + "\n";
    }

    T myMethodOutsideOfClass();
};

template
T MyClass::myMethodOutsideOfClass()
{
    cout << "Inside short implementation \n";
    return 0;
}

int main()
{
    MyClass myClass(1,2);
    myClass.myMethodOutsideOfClass();
    return 0;
}

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь . жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную short , с треском провалилась. прямое преобразование, когда мы используем

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, заключается в использовании || явного шаблона. Это фактический намек компилятору, каким будет тип. Этот метод также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или ththereодин улов в приведенном выше – реализация шаблона все еще должна быть доступна компилятору во время обработки заголовка! Проверьте || этот вопрос SO || для получения дополнительной информации. С четким разделением класса || объявление || от его || определения || – нам это не нужно. Если мы поместим всю логику внутри класса (в то время как он также служит интерфейсом), при каждом изменении в реализации нам придется перекомпилировать код. В C++ (и в C) существует целая концепция динамических/статических библиотек и возможность отделять интерфейс класса с помощью || заголовочных файлов || и использовать только их во время работы/написания кода. Однако, исходя из Java, мы привыкли к тому факту, что наши банки заполнены как интерфейсами, так и реализациями. Что ж, вы правы, так оно и есть. Это глупо и помещает логику класса в два разных места. Как специалисту по Java, мне было интересно – в чем причина определения функции вне класса? ПОДСКАЗКА! Вот пример: Единственное, что нам нужно сделать при реализации метода вне класса, – это добавить к функции имя класса. В качестве дополнительного момента существует возможность реализовать их в методах класса || вне || тела класса (этот метод применим также к определению “обычных” функций). Шаблоны классов || работают очень похоже на || шаблоны функций ||, хотя они определены на уровне класса (спасибо, Капитан Очевидность!). Шаблоны классов Результатом будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, необходимо использовать || явный шаблон. Это фактический намек компилятору, каким будет тип. Этот метод также следует использовать, когда невозможно определить используемый тип из параметров конструктора или поэтому в проектах с несколькими файлами, если мы хотим предоставить заголовок с объявлением класса, все функции, использующие шаблон, также должны быть помещены в один файл! В приведенном выше есть одна загвоздка – реализация шаблона все еще должна быть доступна компилятору во время обработки заголовка! Проверьте || этот вопрос SO || для получения дополнительной информации. С четким разделением класса || объявление || от его || определения || – нам это не нужно. Если мы поместим всю логику внутри класса (в то время как он также служит интерфейсом), при каждом изменении в реализации нам придется перекомпилировать код. В C++ (и в C) существует целая концепция динамических/статических библиотек и возможность отделять интерфейс класса с помощью || заголовочных файлов || и использовать только их во время работы/написания кода. Однако, исходя из Java, мы привыкли к тому факту, что наши банки заполнены как интерфейсами, так и реализациями. Что ж, вы правы, так оно и есть. Это глупо и помещает логику класса в два разных места. Как специалисту по Java, мне было интересно – в чем причина определения функции вне класса? ПОДСКАЗКА! Вот пример: Единственное, что нам нужно сделать при реализации метода вне класса, – это добавить к функции имя класса. В качестве дополнительного момента существует возможность реализовать их в методах класса || вне || тела класса (этот метод применим также к определению “обычных” функций). Шаблоны классов || работают очень похоже на || шаблоны функций ||, хотя они определены на уровне класса (спасибо, Капитан Очевидность!). Шаблоны классов Результатом будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь . жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную short

#include
using namespace std;


template 
class MyClass
{
    public:
    MyClass(T x, T y)
    {
        cout << "My class constructor: " + to_string(x) + " " + to_string(y) + "\n";
    }

    template
    void myMethodOfClass(const U& arg)
    {
        cout << "Passed arg: " + to_string(arg) + "\n";
    }
};

int main()
{
    MyClass myClass(1,2);
    myClass.myMethodOfClass(5);
    myClass.myMethodOfClass(2.0f);
    return 0;
}

или класс в определении шаблона

#include
using namespace std;

template
class Foo
{
public:
    void Func() {}
};

template
class Bar : public Foo
{
public:
    void BarFunc()
    {
        // Func();   This causes compilation error
        this->Func();
        Foo::Func();
    }
};

int main()
{
    Bar b{};
    b.BarFunc();
}

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение – использовать || явный шаблон. Это фактическая подсказка компилятору, каким будет тип. Этот метод также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или шаблонов thAlias, как обычно, вот код: Единственное ограничение здесь заключается в том, что мы должны явно указать компилятору, когда мы хотим использовать функциональность базового класса. В общем, нет никаких проблем с наследованием || шаблонов классов ||. Поскольку мы находимся на объектно-ориентированном языке (более или менее), мы также должны немного поговорить о наследовании. Я думаю, что код объяснит это лучше всего. (обратите внимание на слово ||метод||, а не ||функция ||). Существует также возможность ввести другое шаблонное решение, которое называется || шаблон метода || Когда дело доходит до || шаблонов классов ||, нам не нужно работать только на уровне класса. Вот почему в проектах с несколькими файлами, если мы хотим предоставить заголовок с объявлением класса, все функции, использующие шаблон, также должны быть помещены в один файл! В приведенном выше есть одна загвоздка – реализация шаблона все еще должна быть доступна компилятору во время обработки заголовка! Проверьте || этот вопрос SO || для получения дополнительной информации. С четким разделением класса || объявление || от его || определения || – нам это не нужно. Если мы поместим всю логику внутри класса (в то время как он также служит интерфейсом), при каждом изменении в реализации нам придется перекомпилировать код. В C++ (и в C) существует целая концепция динамических/статических библиотек и возможность отделять интерфейс класса с помощью || заголовочных файлов || и использовать только их во время работы/написания кода. Однако, исходя из Java, мы привыкли к тому факту, что наши банки заполнены как интерфейсами, так и реализациями. Что ж, вы правы, так оно и есть. Это глупо и помещает логику класса в два разных места. Как специалисту по Java, мне было интересно – в чем причина определения функции вне класса? ПОДСКАЗКА! Вот пример: Единственное, что нам нужно сделать при реализации метода вне класса, – это добавить к функции имя класса. В качестве дополнительного момента существует возможность реализовать их в методах класса || вне || тела класса (этот метод применим также к определению “обычных” функций). Шаблоны классов || работают очень похоже на || шаблоны функций ||, хотя они определены на уровне класса (спасибо, Капитан Очевидность!). Шаблоны классов Результатом будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь

template 
class Matrix {
....
};

template 
using Square = Matrix;    // That's the alias

template 
using Vector = Matrix; 

// Code that uses above constructions
Matrix ma;
Square sq;
Vector vec;

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь

или || класс в определении || шаблона ||. Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда || шаблоны шаблонов || были инвоморированы, что || можно найти здесь ||. жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную ||short ||, с треском провалилась. прямое преобразование, когда мы используем || ТЕМ в нашем случае || шаблон || ожидает, что оба аргумента будут одинаковыми, чтобы преодолеть вышеуказанное ограничение, заключается в использовании || явного шаблона. Это фактическая подсказка компилятору, каким будет тип. Этот метод также следует использовать, когда нет способа определить тип, используемый из параметров конструктора или переменных/переменных шаблонов. Он может быть применен к любому другому типу/определению! Идея ||сглаживания || связана не только с ||шаблонами ||! ПОДСКАЗКА! Решение является ясным и читабельным. Как обычно, лучший способ описать эту функциональность – с помощью простого фрагмента кода: Есть еще один способ, которым || шаблоны || могут быть полезны таким образом – || шаблоны псевдонимов Мы уже видели, что || шаблоны || являются отличным инструментом для уменьшения размера кода. Шаблоны псевдонимов Как обычно, вот код: Единственное ограничение здесь заключается в том, что мы должны явно указывать компилятору, когда мы хотим использовать функциональность базового класса. В общем, нет никаких проблем с наследованием || шаблонов классов ||. Поскольку мы находимся на объектно-ориентированном языке (более или менее), мы также должны немного поговорить о наследовании. Я думаю, что код объяснит это лучше всего. (обратите внимание на слово ||метод||, а не ||функция ||). Существует также возможность ввести другое шаблонное решение, которое называется || шаблон метода || Когда дело доходит до || шаблонов классов ||, нам не нужно работать только на уровне класса. Вот почему в проектах с несколькими файлами, если мы хотим предоставить заголовок с объявлением класса, все функции, использующие шаблон, также должны быть помещены в один файл! В приведенном выше есть одна загвоздка – реализация шаблона все еще должна быть доступна компилятору во время обработки заголовка! Проверьте || этот вопрос SO || для получения дополнительной информации. С четким разделением класса || объявление || от его || определения || – нам это не нужно. Если мы поместим всю логику внутри класса (в то время как он также служит интерфейсом), при каждом изменении в реализации нам придется перекомпилировать код. В C++ (и в C) существует целая концепция динамических/статических библиотек и возможность отделять интерфейс класса с помощью || заголовочных файлов || и использовать только их во время работы/написания кода. Однако, исходя из Java, мы привыкли к тому факту, что наши банки заполнены как интерфейсами, так и реализациями. Что ж, вы правы, так оно и есть. Это глупо и помещает логику класса в два разных места. Как специалисту по Java, мне было интересно – в чем причина определения функции вне класса? ПОДСКАЗКА! Вот пример: Единственное, что нам нужно сделать при реализации метода вне класса, – это добавить к функции имя класса. В качестве дополнительного момента существует возможность реализовать их в методах класса || вне || тела класса (этот метод применим также к определению “обычных” функций). Шаблоны классов || работают очень похоже на || шаблоны функций ||, хотя они определены на уровне класса (спасибо, Капитан Очевидность!). Шаблоны классов Результатом будет: Я думаю, что следующий пример покажет, что я имею в виду. В конце этого раздела стоит упомянуть, что есть возможность указать компилятору, какой сгенерированный метод следует вызывать. Описанная выше техника называется ||специализация|| и может быть применена к любому || шаблону функций ||. Взгляните на следующий код: Однако есть возможность предоставить нашу собственную реализацию этих функций, если мы захотим (что-то вроде методов по умолчанию в интерфейсах Java). || это используется в коде. Я упомянул в комментариях к приведенному выше коду, что компилятор создаст фактический код для каждого шаблона || функции, нет способа ограничить их видимость указанной областью. Возвращаясь к свойствам || шаблонов функций || – третье, что следует упомянуть, это то, что || шаблоны функций || могут быть помещены только в глобальное пространство имен. Рассмотрим этот фрагмент кода: e методы. Давайте взглянем на этот пример. e используемая переменная. (да, я знаю, длинное имя). спецификация аргумента te || Никаких исключений! тип пламени, и все. тарелки

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь . жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную short

// Args as a type/name is completely arbitrary and can be anything
template  // this is for the template

void printMyParams(Args... args)  // this is for the function

или класс в определении шаблона . Ну, насколько я читал, это не имеет большого значения (особенно в C++20). До того, как использование было каким-то образом ограничено, когда шаблоны шаблонов были инвоморированы, что можно найти здесь . жил. Третья важная концепция заключается в том, что нет никакой причины, по которой в приведенном выше примере строка, использующая переменную

#include

template 
T sum(T t, Args... args) {
    // [if constexpr] is evaluated during compile time
    // sizeof... is a special operator to determine the amount of params passed
    if constexpr(sizeof...(args) > 0) {  
        return t + sum(args...);
    }

    return t;
}

int main()
{
    std::cout << sum(1,2,3);
}

или класс в определении шаблона

#include

template
T sum(T t)
{
    return t;
}

template
T sum(T t, Args... args) {
    return t + sum(args...);
}

int main()
{
    std::cout << sum(1,2,3);
}

Подводя итог презентации пакетов параметров , я покажу кое-что, что доступно начиная с C++17 – сворачивание (концепция известна из функциональных языков) – если вам интересно, вы можете прочитать об этом на официальной странице .

#include

template
auto sum(Args... args) {
    return (... + args);
}

int main()
{
    std::cout << sum(1,2,3);
}

Члены статического шаблонного класса

Каждая функция или класс могут содержать статические члены. Следует задать широкий вопрос: как они ведут себя, когда используются в шаблонах? Ответ кроется в утверждении, представленном в предыдущем подразделе – шаблоны являются рецептом для создания определенных функций или классов. Следовательно, для каждой вычисляемой комбинации типов компилятор будет генерировать отдельный экземпляр функции/класса. Следовательно, каждый экземпляр будет иметь свой собственный закрытый статический член.

Понятия

В этой статье я просто упомяну их. Во-первых, потому что они заслуживают более описательной статьи, чем просто подраздел здесь. Второе – это новая функция, доступная в C++20. Поэтому он еще не получил широкого распространения. В общем – в Java мы пишем что-то вроде этого:

class MyClass() {
      T someOtherClass;
}

На уровне компиляции мы проверяем, соответствует ли переданный объект критериям расширяет какой-либо другой класс . Это очень мощный инструмент, и именно поэтому C++ также представил его. Однако, как я уже сказал, позже я напишу отдельную статью и свяжу ее здесь.

источники:

От Java до C++ (Серия из 2 частей)

Оригинал: “https://dev.to/chlebik/from-java-to-c-templates-5hf3”