Является ли законным использовать предыдущий параметр функции для объявления нового?
Следующий код компилируется с помощью GCC:
void func(int arg1, decltype(arg1) arg2)
{
(void)arg2;
}
int main(){}
Я использовал эту команду для компиляции:
g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra
Но такое использование параметра в середине объявления функции кажется странным. Действительно ли это действительно в стандартном С++ или это расширение GCC?
Ответы
Ответ 1
Это нормально. ISO C++11 Standard
даже дает вашу ситуацию в качестве примера.
Сначала параметр находится в области видимости:
3.3.3 Область блока [ basic.scope.local ]
2. Потенциальная область имени параметра функции (в том числе одна из них появляется в лямбда-деклараторе) или функция-локальная предопределенная переменная в определении функции (8.4) начинается с момента ее объявления.
Пример можно найти здесь:
8.3.5 Функции [ dcl.fct ]
5 [ Примечание. Это преобразование не влияет на типы параметров. Например, int (*) (const int p, decltype (p) *) и int (*) (int, const int *) являются идентичными типами. - end note ]
Ответ 2
Да, это законно. Это в основном вопрос об объеме. Из [basic.scope.block]:
Потенциальная область имени функционального параметра (в том числе, входящая в лямбда-декларатор) или локально предопределенной функции в определении функции (8.4) начинается с его точки объявления.
Область arg1
начинается здесь:
void func(int arg1, decltype(arg1) arg2)
------------------^
Следовательно, arg1
имеет смысл для объявления arg2
. Я думаю, что это достаточно.
Правило отказа от дефолтного от arg2
до arg1
разделено - мне кажется, что arg1
был в области видимости и должен быть явно запрещен.
Ответ 3
Если мы посмотрим в N3979 [dcl.fct.default], у нас есть
Аргументы по умолчанию оцениваются каждый раз при вызове функции. Порядок оценки аргументов функции не указан. Следовательно, параметры функции не должны использоваться в аргументе по умолчанию, даже если они не оцениваются. Параметры функции, объявленной до аргумента по умолчанию, находятся в области видимости и могут скрывать пространства имен и имена членов класса. [Пример:
int a;
int f(int a, int b = a); // error: parameter a
// used as default argument
typedef int I;
int g(float I, int b = I(2)); // error: parameter I found
int h(int a, int b = sizeof(a)); // error, parameter a used
// in default argument
[...]
Акцент на мине
Итак, в примере a
известно, когда мы переходим к b
, и он скрывает a
от области вызова. Это заставляет меня думать, что каждый параметр функции известен перед каждым последующим параметром. Это означает, что вы должны использовать его тип. Вы не можете использовать его значение - поскольку порядок оценки значений не указан, но имена должны вводиться в порядке слева направо.