Подтвердить что ты не робот

Является ли законным использовать предыдущий параметр функции для объявления нового?

Следующий код компилируется с помощью 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?

4b9b3361

Ответ 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 от области вызова. Это заставляет меня думать, что каждый параметр функции известен перед каждым последующим параметром. Это означает, что вы должны использовать его тип. Вы не можете использовать его значение - поскольку порядок оценки значений не указан, но имена должны вводиться в порядке слева направо.