Для этой функции указано больше аргументов, чем разрешено форматом файла
Обновлено: 20.11.2024
export был необязательным модификатором, который объявлял шаблон как экспортированный (при использовании с шаблоном класса он также объявлял все его члены экспортированными). Файлы, которые создавали экземпляры экспортированных шаблонов, не должны были включать их определения: достаточно было объявления. Реализации экспорта были редки и расходились друг с другом в деталях.
Сокращенный шаблон функции
Когда в списке параметров объявления функции или объявления шаблона функции появляются типы заполнителей (auto или Concept auto), это объявление объявляет шаблон функции, и к параметру шаблона добавляется один параметр искусственного шаблона для каждого заполнителя. список:
Сокращенные шаблоны функций могут быть специализированы, как и все шаблоны функций.
[edit] Создание экземпляра шаблона функции
Шаблон функции сам по себе не является типом, функцией или какой-либо другой сущностью. Код из исходного файла, содержащего только определения шаблонов, не создается. Чтобы код отображался, необходимо создать экземпляр шаблона: аргументы шаблона должны быть определены таким образом, чтобы компилятор мог сгенерировать фактическую функцию (или класс из шаблона класса).
[edit] Явное создание экземпляров
<таблица>1) Явное определение создания экземпляра (без вывода аргумента шаблона, если явно указан каждый параметр шаблона, отличный от значения по умолчанию)
3) Явное объявление создания экземпляра (без вывода аргумента шаблона, если явно указан каждый параметр шаблона, отличный от значения по умолчанию)
Явное определение создания экземпляра приводит к созданию экземпляра функции или функции-члена, на которую они ссылаются. Он может появиться в программе в любом месте после определения шаблона, и для данного списка аргументов разрешено появляться в программе только один раз, диагностика не требуется.
Явное объявление создания экземпляра (внешний шаблон) предотвращает неявное создание экземпляра: код, который в противном случае вызвал бы неявное создание экземпляра, должен использовать определение явного создания экземпляра, предоставленное где-то еще в программе.
Конечный аргумент шаблона можно не указывать в явной реализации специализации шаблона функции или специализации шаблона функции-члена, если его можно вывести из параметра функции:
Явное создание экземпляра шаблона функции или функции-члена шаблона класса не может использовать inline или constexpr . Если в объявлении явного создания экземпляра содержится имя неявно объявленной специальной функции-члена, программа имеет неправильный формат.
Явное создание экземпляра конструктора не может использовать список параметров шаблона (синтаксис (1)), что также никогда не требуется, поскольку их можно вывести (синтаксис (2)).
Явное создание экземпляра предполагаемого деструктора должно называть выбранный деструктор класса.
Явные объявления реализации не подавляют неявную реализацию встроенных функций, автоматических объявлений, ссылок и специализаций шаблонов классов. (таким образом, когда встроенная функция, являющаяся предметом явного объявления инстанцирования, используется ODR, она неявно создается для встраивания, но ее внешняя копия не генерируется в этой единице трансляции)
Явное определение экземпляра шаблона функции с аргументами по умолчанию не использует аргументы и не пытается их инициализировать:
[edit] Неявное создание экземпляров
Когда код ссылается на функцию в контексте, требующем существования определения функции, или если существование определения влияет на семантику программы (начиная с C++11), и эта конкретная функция не была создана явно, происходит неявное инстанцирование. Список аргументов шаблона указывать необязательно, если его можно вывести из контекста.
Считается, что наличие определения функции влияет на семантику программы, если функция необходима для постоянного вычисления выражения, даже если постоянное вычисление выражения не требуется или если вычисление константного выражения не использует определение.
Примечание: полный пропуск <> позволяет анализировать перегрузки для проверки как шаблонных, так и не шаблонных перегрузок.
[править] Вывод шаблонных аргументов
Чтобы создать экземпляр шаблона функции, должен быть известен каждый аргумент шаблона, но не обязательно указывать каждый аргумент шаблона.Когда это возможно, компилятор выведет отсутствующие аргументы шаблона из аргументов функции. Это происходит при попытке вызова функции и при взятии адреса шаблона функции.
Этот механизм позволяет использовать шаблонные операторы, поскольку нет синтаксиса для указания аргументов шаблона для оператора, кроме как путем перезаписи его как выражения вызова функции.
Вывод аргумента шаблона происходит после поиска имени шаблона функции (который может включать поиск, зависящий от аргумента) и перед разрешением перегрузки.
[edit] Явные аргументы шаблона
Аргументы шаблона шаблона функции могут быть получены из
- вывод шаблонного аргумента
- аргументы шаблона по умолчанию
- указано явно, что может быть сделано в следующих контекстах:
- в выражении вызова функции
- когда берется адрес функции
- при инициализации ссылки на функцию
- при формировании указателя на функцию-член
- в явной специализации
- в явном воплощении
- в объявлении друга
Невозможно явно указать аргументы шаблона для перегруженных операторов, функций преобразования и конструкторов, поскольку они вызываются без использования имени функции.
Указанные аргументы шаблона должны соответствовать параметрам шаблона по типу (т. е. тип для типа, нетип для нетипа и шаблон для шаблона). Аргументов не может быть больше, чем параметров (если только один параметр не является пакетом параметров, в этом случае должен быть аргумент для каждого параметра, не входящего в пакет)
Указанные нетиповые аргументы должны либо соответствовать типам соответствующих нетиповых параметров шаблона, либо быть конвертируемыми в них.
Параметры функции, которые не участвуют в выводе аргументов шаблона (например, если соответствующие аргументы шаблона указаны явно), подлежат неявному преобразованию в тип соответствующего параметра функции (как при обычном разрешении перегрузки).
Пакет параметров шаблона, указанный явно, может быть расширен за счет вывода аргументов шаблона, если есть дополнительные аргументы:
[edit] Подстановка аргументов шаблона
Когда все аргументы шаблона указаны, выведены или получены из аргументов шаблона по умолчанию, каждое использование параметра шаблона в списке параметров функции заменяется соответствующими аргументами шаблона.
Ошибка подстановки (то есть сбой замены параметров шаблона выведенными или предоставленными аргументами шаблона) шаблона функции удаляет шаблон функции из набора перегрузки. Это позволяет несколькими способами манипулировать перегруженными наборами с помощью метапрограммирования шаблонов: подробности см. в SFINAE.
После подстановки все параметры функции массива и типа функции преобразуются в указатели, а все квалификаторы cv верхнего уровня удаляются из параметров функции (как в обычном объявлении функции).
Удаление cv-квалификаторов верхнего уровня не влияет на тип параметра, который появляется в функции:
[править] Перегрузка шаблона функции
Шаблоны функций и нешаблонные функции могут быть перегружены.
Функция, не являющаяся шаблоном, всегда отличается от специализации шаблона того же типа. Специализации различных шаблонов функций всегда отличаются друг от друга, даже если они имеют один и тот же тип. Два шаблона функций с одинаковым типом возвращаемого значения и одним и тем же списком параметров различны и могут быть различимы с помощью явного списка аргументов шаблона.
Когда выражение, использующее параметры шаблона типа или нетипа, появляется в списке параметров функции или в возвращаемом типе, это выражение остается частью подписи шаблона функции для целей перегрузки:
Два выражения, включающие параметры шаблона, называются эквивалентными, если два определения функций, содержащие эти выражения, были бы одинаковыми в ODR, то есть два выражения содержат одну и ту же последовательность токенов, имена которых разрешаются в одни и те же объекты с помощью поиска по имени, за исключением того, что параметры шаблона могут называться по-разному. Два лямбда-выражения никогда не эквивалентны. (начиная с C++20)
При определении эквивалентности двух зависимых выражений учитываются только задействованные зависимые имена, а не результаты поиска имен. Если несколько объявлений одного и того же шаблона отличаются в результате поиска имени, используется первое такое объявление:
Два шаблона функций считаются эквивалентными, если
- они объявлены в одной области действия
- у них одинаковое имя
- они имеют эквивалентные списки параметров шаблона, что означает, что списки имеют одинаковую длину, и для каждой соответствующей пары параметров верно все следующее:
- два параметра относятся к одному типу (оба типа, оба нетипа или оба шаблона)
- они либо оба являются пакетами параметров, либо ни один из них
- если не тип, их типы эквивалентны,
- если шаблон, их параметры шаблона эквивалентны,
- если один из них объявлен с именем понятия, они оба являются эквивалентными, и имена понятий эквивалентны.
- выражения, включающие параметры шаблона в возвращаемых типах и списках параметров, эквивалентны
- выражения в их предложениях, которые следуют за списками параметров шаблона, если они присутствуют, эквивалентны
- выражения в их предложениях-требованиях, которые следуют за деклараторами функций, если они присутствуют, эквивалентны
Два выражения, включающие параметры шаблона, называются функционально эквивалентными, если они не эквивалентны, но для любого заданного набора аргументов шаблона оценка двух выражений приводит к то же значение.
Два шаблона функций считаются функционально эквивалентными, если они эквивалентны, за исключением того, что одно или несколько выражений, включающих параметры шаблона в свои возвращаемые типы и списки параметров, функционально эквивалентны.
Кроме того, два шаблона функций функционально эквивалентны, но не эквивалентны, если их ограничения указаны по-разному, но они принимают и удовлетворяются одним и тем же набором списков аргументов шаблона. .
Если программа содержит объявления шаблонов функций, которые функционально эквивалентны, но не эквивалентны, программа некорректна; диагностика не требуется.
Когда одна и та же специализация шаблона функции соответствует более чем одному шаблону перегруженной функции (часто это происходит в результате вывода аргументов шаблона), выполняется частичное упорядочение шаблонов перегруженных функций для выбора наилучшего соответствия.
В частности, частичное упорядочение имеет место в следующих ситуациях:
3) когда выбран оператор размещения delete, который является специализацией шаблона функции, чтобы соответствовать оператору размещения new:Этот раздел неполный Причина: mini -пример |
4) когда объявление дружественной функции, явное создание экземпляра или явная специализация ссылаются на специализацию шаблона функции:
Неофициально "A более специализирован, чем B" означает "A принимает меньше типов, чем B".
Формально, чтобы определить, какой из любых двух шаблонов функций является более специализированным, процесс частичного упорядочивания сначала преобразует один из двух шаблонов следующим образом:
- Для каждого параметра типа, нетипа и шаблона, включая пакеты параметров, создается уникальный фиктивный тип, значение или шаблон, который подставляется в тип функции шаблона
- Если только один из двух сравниваемых шаблонов функций является функцией-членом и этот шаблон функции является нестатическим членом некоторого класса A , в его список параметров вставляется новый первый параметр, тип которого — cv A&&, если шаблон функции-члена имеет квалификацию && и cv A& в противном случае (cv — это cv-квалификация шаблона функции-члена) — это помогает упорядочивать операторы, которые просматриваются как функции-члены, так и функции, не являющиеся членами: ли>
После преобразования одного из двух шаблонов, как описано выше, выполняется вывод аргумента шаблона с использованием преобразованного шаблона в качестве шаблона аргумента и исходного типа шаблона другого шаблона в качестве шаблона параметра. Затем процесс повторяется с использованием второго шаблона (после преобразований) в качестве аргумента и первого шаблона в его исходной форме в качестве параметра.
Типы, используемые для определения порядка, зависят от контекста:
- в контексте вызова функции типы — это те типы параметров функции, для которых вызов функции имеет аргументы (аргументы функции по умолчанию, пакеты параметров и параметры с многоточием не учитываются — см. примеры ниже)
- в контексте вызова определяемой пользователем функции преобразования используются возвращаемые типы шаблонов функции преобразования
- в других контекстах используется тип шаблона функции
Каждый тип из списка выше выводится из шаблона параметра. Перед началом вывода каждый параметр P шаблона параметра и соответствующий аргумент A шаблона аргумента настраиваются следующим образом:
- Если и P, и A ранее были ссылочными типами, определите, какой из них больше подходит для cv (во всех остальных случаях cv-квалификации игнорируются для целей частичного упорядочения)
- Если P является ссылочным типом, он заменяется типом, на который указывает ссылка
- Если A является ссылочным типом, он заменяется типом, на который указывает ссылка
- Если P является cv-квалифицированным, P заменяется своей cv-неквалифицированной версией
- Если A является cv-квалифицированным, A заменяется cv-неквалифицированной версией самого себя.
После этих корректировок вывод P из A выполняется после вывода аргумента шаблона из типа.
Если P является пакетом параметров функции, тип A каждого оставшегося типа параметра шаблона аргумента сравнивается с типом P идентификатора декларатора пакета параметров функции. Каждое сравнение выводит аргументы шаблона для последующих позиций в пакетах параметров шаблона, расширенных пакетом параметров функции.
Если A был преобразован из пакета параметров функции, он сравнивается с каждым оставшимся типом параметра шаблона параметра.
Если аргумент A преобразованного шаблона-1 может быть использован для вывода соответствующего параметра P шаблона-2, но не наоборот, то этот A является более специализированным, чем P, в отношении типов, которые выводится этой парой P/A.
Если дедукция успешна в обоих направлениях, а исходные P и A были ссылочными типами, то проводятся дополнительные проверки:
- Если A было ссылкой lvalue, а P — ссылкой rvalue, A считается более специализированным, чем P
- Если A имеет более высокую квалификацию, чем P , A считается более специализированным, чем P
Во всех остальных случаях ни один из шаблонов не является более специализированным, чем другой, в отношении типов, выводимых этой парой P/A.
После рассмотрения всех P и A в обоих направлениях, если для каждого рассмотренного типа
- шаблон-1 не менее специализирован, чем шаблон-2 для всех типов
- template-1 является более специализированным, чем template-2 для некоторых типов
- шаблон-2 не более специализирован, чем шаблон-1, для любых типов ИЛИ, по крайней мере, не так специализирован ни для каких типов
Тогда шаблон-1 более специализирован, чем шаблон-2. Если вышеуказанные условия выполняются после переключения порядка шаблонов, то шаблон-2 является более специализированным, чем шаблон-1. В противном случае ни один из шаблонов не является более специализированным, чем другой. В случае совпадения, если один шаблон функции имеет завершающий пакет параметров, а другой нет, шаблон с пропущенным параметром считается более специализированным, чем шаблон с пустым пакетом параметров.
Если после рассмотрения всех пар перегруженных шаблонов один из них однозначно является более специализированным, чем все остальные, выбирается специализация этого шаблона, иначе компиляция завершится неудачно.
В следующих примерах фиктивные аргументы будут называться U1, U2:
Вы, наверное, заметили, что в функциях используются круглые скобки, а внутри этих круглых скобок находятся определенные входные данные. Эти входные данные имеют специальное имя: arguments.
Давайте рассмотрим несколько примеров.
Аргументы могут быть обязательными или необязательными. Некоторые функции принимают три или более аргумента, а некоторые вообще не принимают никаких аргументов.
Хорошим примером функции без аргументов является функция СЕГОДНЯ, которая возвращает текущую дату. Чтобы использовать его, просто введите знак равенства, СЕГОДНЯ и пустые скобки.
Другие функции принимают несколько аргументов; все это требуется. Хорошим примером является функция DATE, которая позволяет построить допустимую дату, используя год, месяц и день в качестве отдельных и обязательных аргументов.
Обратите внимание, что при вводе функции, которую Excel распознает, Excel отобразит всплывающее окно с информацией обо всех аргументах.
Текущий аргумент будет выделен жирным шрифтом. Каждый дополнительный аргумент должен быть разделен запятой. По мере ввода аргументов и запятых каждый аргумент будет выделен жирным шрифтом по очереди.
Обратите внимание, что Excel не заботится о том, следуют ли за запятыми пробелы или нет.
Некоторые функции имеют необязательные аргументы, которые отображаются в квадратных скобках внутри окна подсказки формулы.
Примером функции, которая принимает необязательный аргумент, является функция ROW. Без каких-либо аргументов СТРОКА возвращает строку ячейки, в которой она находится. Однако, если вы укажете ссылку, СТРОКА вернет номер строки этой ссылки. Например, если мы указываем H10 в качестве ссылки, ROW возвращает число 10.
Некоторые функции могут принимать большое количество необязательных аргументов. Хорошим примером является функция СУММ. Концепция дополнительных необязательных аргументов выражается многоточием, которое появляется в конце списка аргументов, когда функция принимает несколько необязательных аргументов.
Фактически функция SUM может принимать до 256 аргументов. Используя запятые для разделения аргументов, мы можем легко суммировать содержимое многих ячеек одновременно. Небольшой трюк, который вы можете использовать с функцией СУММ, заключается в том, чтобы удерживать нажатой клавишу Control при выборе дополнительных ячеек. Затем Excel добавит запятые за вас.
Во многих случаях вы не будете предоставлять аргументы в виде жестко закодированных значений, так как это сводит на нет всю мощь электронной таблицы. Вместо этого вы будете указывать значения из других ячеек.
Например, функция ДАТАМЕС принимает два аргумента: дату начала и месяцы, а затем возвращает ту же дату в будущем или прошлом.
Когда вы предоставляете аргументы в виде ячеек на листе, вы можете указывать ссылки на ячейки в качестве аргументов. Это позволяет позже легко изменить входные значения и получить другой результат от функции.
На этой странице описаны определения многих из терминов, описание для описания функций в функциях.
Любой тип значения
Если аргумент задан как любой, он может быть связан значением, значением даты/времени, значением длительности, числовым значением или строковым значением.
Массивы и функции, возвращающие массивы
Массив — это последовательность зависимостей, возвращаемых или возвращаемых значений. Функция, возвращающая массив, возвращает массив значений, а не отдельное значение. Эти функции обычно используются для предоставления значений других функций.
Булево выражение и тип значения
Логическое (булево) выражение — это выражение, которое имеет значение логического ИСТИНА или ЛОЖЬ. Булево (логическое) значение — это либо дает важное логическое значение ИСТИНА (1) или ЛОЖЬ (0), либо ссылка на ячейку, которая содержит или в результате логического значения ИСТИНА или ЛОЖЬ. Обычно булево значение имеет высокую степень логического выражения, однако булево значение может быть также увеличено как непосредственная функция или содержимое. Булево значение, обычно используемое для определения выражения, возвращаемого выражения ЕСЛИ.
Значение воздействия
Аргумент, заданный как множество, может являться ссылкой на один диапазон таблиц таблицы или на массив, возвращаемый числовыми значениями. Аргумент, заданный как множество, имеет дополнительный атрибут, получаемый тип, содержащийся в нем значениях.
Условное выражение
Условие — это выражение, которое может проявляться в себе операторы сравнения, константы, оператора объединения строк (амперсанд) и ссылок. Результатом сравнения условий с другим значением должно быть логическое значение ИСТИНА или ЛОЖЬ.
Постоянное выражение
Значение даты/времени
Значение числа/времени — это значение числа/времени или привязка к ячейке, которая содержит значение числа/времени, в зависимости от формата, соответствующих чисел. Можно настроить ячейку для отображения только даты или времени, однако все значения даты/времени составляют как заданное, так и время.
Значение длительности
Значение списка
Список — это последовательность различных измерений с разделением измерений запятыми. Например:
В некоторых случаях приводится список дополнительных пар скобок. Например:
Значение аргумента перечислимого типа
Аргумент перечисления типа может принимать значение только из заданного набора значений. Как правило, аргументы перечислимого типа задают тип основных вычислений или тип возвращаемых чисел данных. Если аргумент перечислимого типа имеет значение по умолчанию, это добавление в описание аргумента.
Числовое значение
Числовое значение — это число, числовое выражение или ссылка на ячейку, содержащую числовое выражение. Если допустимые значения числа ограничены (например, числовое значение должно быть больше 0), обнаружение попадания в описание аргумента.
Значение почты
Значение блокировки — это ссылка на один диапазон ячеек (может быть одной и ячейкой). Значение имеет дополнительный атрибут, уведомляемый в описании. Это показатели, которые должны соответствовать диапазону частот.
Значение ссылок
Значение ссылок — это ссылка на отдельную ячейку или диапазон ячеек.
Если диапазон содержит более одной клетки, начальную и конечную концентрацию уравновешивают двоеточием. Например:
Если ссылка на ячейку в таблице указана, ссылка приведена в таблице. Например:
Обратите внимание на то, что заголовок таблицы и ссылка на ячейку усилены двоеточием (::). При выборе варианта в таблице время построения формулы имени таблицы в посиланне автоматически.
В случае обращения к ячейке таблицы, размещенной на слайде с изображением слайда, ссылка должна содержать имя слайда. Например:
СУММ(Слайд 2::Таблица 1::C2:G2).
Имена объектов и ссылки на увеличенные белки. При выборе ячейки на слайде во время построения формулы имени слайда и таблицы автоматически включаются в формуляр.
Строковое значение
Строковое значение — это ноль или более символов или ссылка на ячейку, содержащую ноль или более символов. Символами могут быть любые печатаемые символы, включая цифры.
В этом разделе содержится справочная информация об ошибках Amazon S3.
Темы
Ответы на ошибки REST
При возникновении ошибки информация в заголовке содержит следующее:
Тело ответа также содержит информацию об ошибке. В следующем образце ответа об ошибке показана структура элементов ответа, общих для всех ответов об ошибках REST.
В следующей таблице объясняются элементы ответа на ошибку REST.
Код ошибки – это строка, однозначно идентифицирующая состояние ошибки. Он предназначен для чтения и понимания программами, которые обнаруживают и обрабатывают ошибки по типу. Дополнительные сведения см. в разделе Список кодов ошибок.
Контейнер для всех элементов ошибок.
Сообщение об ошибке содержит общее описание состояния ошибки на английском языке. Он предназначен для человеческой аудитории. Простые программы отображают сообщение непосредственно конечному пользователю, если он сталкивается с ошибкой, которую не знает, как или не хочет обрабатывать. Сложные программы с более исчерпывающей обработкой ошибок и правильной интернационализацией с большей вероятностью проигнорируют сообщение об ошибке.
Идентификатор запроса, связанного с ошибкой.
Корзина или объект, вызвавший ошибку.
Многие ответы об ошибках содержат дополнительные структурированные данные, предназначенные для прочтения и понимания разработчиком, выполняющим диагностику программных ошибок. Например, если вы отправляете заголовок Content-MD5 с запросом REST PUT, который не соответствует дайджесту, рассчитанному на сервере, вы получаете ошибку BadDigest. Ответ об ошибке также включает в качестве элементов сведений дайджест, рассчитанный сервером, и дайджест, который вы сказали серверу ожидать. Во время разработки вы можете использовать эту информацию для диагностики ошибки. В рабочей среде хорошо работающая программа может включить эту информацию в свой журнал ошибок.
Информацию об общих элементах ответа см. в разделе "Ответы об ошибках".
Список кодов ошибок
В следующей таблице перечислены коды ошибок Amazon S3.
Для Amazon S3 на Outposts корзина, которую вы пытались создать, уже существует в вашей Outpost и принадлежит вам.
409 Конфликт (во всех регионах, кроме us-east-1)
Эта ошибка может возникнуть по следующим причинам:
Указанный аргумент недействителен.
В запросе отсутствовал обязательный заголовок.
Указанный аргумент был неполным или имел неверный формат.
Указанный аргумент должен иметь длину больше или равную 3.
Эта ошибка может возникнуть по следующим причинам:
В запросе используется неправильная версия подписи. Используйте AWS4-HMAC-SHA256 (версия подписи 4).
Точку доступа можно создать только для существующего сегмента.
Точка доступа не может быть удалена.
Точка доступа может быть указана только для существующего сегмента.
Следующий токен недействителен.
В правиле жизненного цикла должно быть указано хотя бы одно действие.
Необходимо указать хотя бы одно правило жизненного цикла.
Количество правил жизненного цикла не должно превышать разрешенного предела в 1000 правил.
Недопустимый диапазон параметра MaxResults.
Amazon S3 Transfer Acceleration не поддерживается для корзин с именами, несовместимыми с DNS.
Amazon S3 Transfer Acceleration не поддерживается для сегментов с точками (.) в именах.
Конечная точка Amazon S3 Transfer Acceleration поддерживает только запросы виртуального стиля.
Ускорение передачи Amazon S3 не настроено для этого сегмента.
Ускорение передачи Amazon S3 отключено в этом сегменте.
Ускорение передачи Amazon S3 не поддерживается в этом сегменте. Для получения помощи обратитесь в службу поддержки AWS .
Ускорение передачи Amazon S3 нельзя включить для этого сегмента. Для получения помощи обратитесь в службу поддержки AWS .
Указанный тег не существует.
Список кодов ошибок содержимого объекта SELECT
В следующей таблице приведены специальные ошибки, которые может возвращать SELECT Object Content. Общие сведения об ошибках Amazon S3 и список кодов ошибок см. в разделе Ответы на ошибки.
Список кодов ошибок, связанных с репликацией
В следующей таблице приведены специальные ошибки, которые может возвращать операция репликации. Общие сведения об ошибках Amazon S3 и список кодов ошибок см. в разделе Ответы на ошибки.
Читайте также: