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

Можно ли инициализировать аргумент по умолчанию С++ с помощью другого аргумента?

Для аргумента по умолчанию в С++ значение должно быть константой или будет использоваться другой аргумент?

То есть, может ли следующая работа?

RateLimiter(unsigned double rateInPermitsPerSecond, 
            unsigned int maxAccumulatedPermits = rateInPermitsPerSecond);

В настоящее время я получаю сообщение об ошибке:

RateLimiter.h: 13: error: 'rateInPermitsPerSecond не был объявлен в этой области

4b9b3361

Ответ 1

Другой аргумент не может использоваться как значение по умолчанию. Стандартные состояния:

8.3.6 Аргументы по умолчанию


9 Аргумент по умолчанию оценивается каждый раз, когда функция вызывается без аргумента для соответствующего параметр. Порядок оценки аргументов функции не указан. Следовательно, параметры функция не должна использоваться в аргументе по умолчанию, даже если они не оцениваются.

и иллюстрирует его следующим примером:

int f(int a, int b = a); // error: parameter a
                         // used as default argument

Ответ 2

Нет, это невозможно, потому что оценка аргументов функции не секвенирована. Он также не работает, потому что стандарт не позволяет этого, но я думаю, это было очевидно.

Вместо этого используйте перегрузку:

void fun(int, int) {}

void fun(int i) {
    fun(i, i);
}

Ответ 3

Я искал логическое объяснение того, почему это не разрешено

Это действительно хороший вопрос. Причина в том, что С++ не задает порядок оценки аргументов.

Итак, представьте себе несколько более сложный сценарий:

int f(int a, int b = ++a);

... followed by ...

int a = 1;
f(a);

С++ не задает порядок оценки аргументов, помните?

Итак, каково должно быть значение b?

f(a) может оценить либо:

f(1, 2), или f(2, 2), в зависимости от порядка оценки аргументов.

Таким образом, поведение будет undefined (и даже не определено).

Далее рассмотрим, что может произойти, когда a и b являются сложными объектами, у конструкторов и операторов копирования были побочные эффекты.

Порядок этих побочных эффектов будет undefined.

Ответ 4

Вы не можете так поступать, потому что стандарт этого не позволяет. Однако, поскольку аргументы по умолчанию эффективно определяют новые перегрузки функций, вы можете получить желаемый эффект, явно определяя такую ​​перегрузку:

void RateLimiter(unsigned int rateInPermitsPerSecond, 
                 unsigned int maxAccumulatedPermits);

inline void RateLimiter(unsigned int rateInPermitsPerSecond)
{ return RateLimiter(rateInPermitsPerSecond,rateInPermitsPerSecond); }

Это показывает, что стандарт, запрещающий это, является половинчатым, как предлагает язык ( "Следовательно... не должен..." ). Они просто не хотели переживать хлопоты, чтобы сделать это хорошо определенным с тем же эффектом, что и явное объявление о перегрузке: при желании они могли бы указать, что аргументы по умолчанию оцениваются после явно предоставленных, а слева направо, Это не повлияло бы на правило, что порядок оценки выражений аргументов в вызове функции не указан (поскольку аргументы по умолчанию не соответствуют таким выражениям, они полностью раздельны и даже не в той же лексической области). С другой стороны, если (как они это сделали), они предпочли запретить это, они могли бы просто сказать "не должны" без необходимости оправдываться из какого-либо другого правила (но, возможно, с пояснительной сноской).

Ответ 5

Для аргумента по умолчанию в С++ значение должно быть константой или будет использоваться другой аргумент?

Значение аргумента по умолчанию не может быть другим аргументом. Однако это не означает, что он должен быть постоянным. Это может быть возвращаемое значение вызова функции.

int getNextDefaultID()
{
   static int id = 0;
   return ++id;
}

struct Foo
{
   Foo(int data, int id = getNextDefaultID()) : data_(data), id_(id) {}
   int data_;
   int id_;
};

int main()
{
    Foo f1(10);      // Gets the next default ID.
    Foo f2(20, 999); // ID is specified.
}