Капитан Педантик на помощь!
Если вы напишите
int(value)
Это то, что известно как явное преобразование типов и регулируется разделом 5.2.3. Точная формулировка гласит, что
Спецификатор простого типа (7.1.5), за которым следует список выражений в скобках, создает значение указанного типа по списку выражений. Если список выражений является одним выражением, выражение преобразования типа эквивалентно (в определенности и если определено в значении) соответствующему приведенному выражению (5.4)
(мой акцент). Так что это означает, что
int(value)
и
(int)value
полностью идентичны друг другу. Вам решать, какой из них вам легче написать.
Что касается вашего второго вопроса, в примере, который вы дали с шаблонами и массивом, я думаю, что вы хотели написать что-то вроде этого.
template <typename T, size_t N>
size_t (T (&)[N]) {
return N;
}
Здесь N
, а также T
- это параметр шаблона, который позволяет вам передавать любой массив, который вы хотите, при этом компилятор заполняет N
числом элементов в массиве. Если это выглядит странно (что на самом деле означает T (&)[N]
?), Это потому, что эта функция принимает параметр типа T (&)[N]
. Чтобы сделать это немного легче для чтения, давайте дадим этому параметру имя, как показано здесь:
template <typename T, size_t N>
size_t (T (&array)[N]) {
return N;
}
Я думаю, это немного облегчает чтение. Но что означает эта декларация?
T (&array)[N]
Здесь объявляется переменная с именем array
, которая является ссылкой на массив T
с точно N
элементов. Вы действительно можете объявить ссылки на массивы так же, как вы можете объявить указатели на массивы. На практике это не очень распространено, но в данном конкретном шаблоне идиома является отличным способом заставить компилятор определить размер массива для вас, когда он пытается сопоставить массив с аргументом шаблона.
Причиной использования круглых скобок в этом случае является то, что если вы напишите
T& array[N]
Компилятор будет анализировать это как "переменную с именем array
, которая является массивом N
объектов, каждый из которых является T&
. Однако спецификация C ++ специально запрещает массивы ссылок, и это будет недопустимым Скобки явно устраняют неоднозначность. Это похоже на указатели на функции - вы пишете
void (*functionPointer)()
вместо
void *functionPointer()
Чтобы заставить компилятор понять, что *
означает, что functionPointer
является указателем, а не функцией, которая возвращает void *
.
Что касается того, как компилятор определяет, когда обрабатывать скобки каждым способом, правила довольно сложны, и на самом деле есть несколько обстоятельств, при которых компилятор не будет анализировать ваше выражение по назначению. Одним из этих случаев является то, что в разговорной речи называют «самым неприятным синтаксическим анализом», в котором компилятор рассматривает то, что выглядит как конструирование объекта, как прототип функции. Как пример, этот код:
vector<int> v();
не создает vector<int>
с именем v
, инициализированный с использованием конструктора по умолчанию. Вместо этого он обрабатывает это как прототип функции для функции с именем v
, которая не принимает аргументов и создает vector<int>
! Однако, если бы вы написали
vector<int> v(10);
Тогда компилятор может однозначно сделать вывод, что это объявление vector<int>
, передающее 10
в качестве аргумента конструктора, поскольку нет способа, чтобы его можно было рассматривать как прототип функции. & gt; 6.8 и & sect; 8.2 спецификации обрабатывают эти случаи, говоря, что все, что может быть обработано как объявление, будет, и все, что может быть обработано как прототип функции, будет также.
Случай скобок в контексте массива (то есть T (&array)[N]
) обрабатывается другой частью логики, потому что в контексте, в котором вы объявляете переменную или определяете параметр, тип которого требует явных скобок , не может быть никакой двусмысленности относительно вашего намерения, поскольку из контекста ясно, что вы называете тип для объявления переменной.
Подведем итог -
- Приведения формы
T(value)
и (T)value
идентичны.
- Скобки в
T (&array)[N]
предназначены для предотвращения привязки компилятором &
к T
вместо array
, как предполагалось.
- Конкретное использование скобок обычно определяется из контекста, хотя некоторые проблемы могут возникать между объявлениями переменных и прототипами функций.
Надеюсь, это поможет!