Почему разрешен пакет параметров после аргументов по умолчанию?

Может быть, я упускаю что-то очевидное, но следующее компилируется и запускается, и я не уверен, почему. Я знаю об этом , но в приведенном ниже примере пакет параметров и аргумент по умолчанию меняются местами. Разве это не нарушает правило, согласно которому аргументы по умолчанию должны стоять последними? Пакет параметров не может иметь значение по умолчанию.

#include <iostream>
#include <string>
#include <tuple>

template<typename ... Ts>
struct Test
{
    int i;
    std::string str;

    Test(int _i = 0, Ts&& ... _ts)
        :
          i(_i),
          str(std::get<0>(std::forward_as_tuple(std::forward<Ts>(_ts)...)))
    {}
};

int main()
{
    Test<std::string> t(1, "huh??");
    std::cout << "t.i = " << t.i << ", t.str = " << t.str << "\n";

    return 0;
}

Это производит

t.i = 1, t.str = huh??

person cantordust    schedule 16.11.2017    source источник
comment
Разве не пусто по умолчанию для любого пакета параметров?   -  person Walter    schedule 17.11.2017
comment
да, пустое значение по умолчанию..   -  person ΦXocę 웃 Пepeúpa ツ    schedule 17.11.2017


Ответы (3)


Начиная с 8.3.6 ([dcl.fct.default])/4:< /а>

Для нешаблонных функций аргументы по умолчанию могут быть добавлены в более поздние объявления функции в той же области. Объявления в разных областях имеют совершенно разные наборы аргументов по умолчанию. То есть объявления во внутренних областях не получают аргументы по умолчанию из объявлений во внешних областях, и наоборот. В данном объявлении функции каждый параметр, следующий за параметром с аргументом по умолчанию, должен иметь аргумент по умолчанию, предоставленный в этом или предыдущем объявлении, или должен быть пакетом параметров функции. Аргумент по умолчанию не должен переопределяться. более поздним объявлением (даже не на то же значение). [ Пример:

void g(int = 0, ...); // OK, ellipsis is not a parameter. So it can follow a parameter with a default argument
person msc    schedule 16.11.2017
comment
(Придирка) Это не отвечает на вопрос (что было не так, но почему это разрешено). - person Walter; 17.11.2017
comment
@Walter Я думаю, что наиболее разумный способ интерпретировать это почему, в свете стандарта, компилятор допускает это? - person Kyle Strand; 17.11.2017
comment
@KyleStrand У тебя есть, а у меня нет. Скорее, я думаю, что наиболее разумной интерпретацией является почему стандарт разрешает это? Обратите также внимание, что вопрос не помечен как language-lawyer. В общем, самый разумный ответ на вопрос почему разрешено то-то и то-то не потому что таков закон. Если, возможно, вы не юрист. - person Walter; 17.11.2017
comment
@Walter Обратите внимание на комментарий OP в ответ на этот ответ и тот факт, что они приняли его как ответ. Кроме того, эти ключевые выдержки из вопроса: ... следующее компилируется и запускается, и я не уверен, почему. (То есть, OP не уверен, почему он компилируется.) И не нарушает ли это правило, согласно которому аргументы по умолчанию должны отображаться последними? (Это вопрос о том, каковы правила.) - person Kyle Strand; 17.11.2017
comment
@KyleStrand Я так и знал: ты юрист! ;-) - person Walter; 17.11.2017
comment
Правда, я принял ответ, основываясь на том факте, что это закон, но теперь, когда вы упомянули об этом... в каких случаях это было бы полезно? Я, наверное, должен задать отдельный вопрос... - person cantordust; 17.11.2017
comment
@cantordust Чтобы избавить вас от некоторых проблем: почему на вопросы такого рода часто отвечают с некоторыми вариациями того, как мы должны знать? Вы должны спросить комитет по стандартам. Возможно, между участниками есть записи обсуждения того, следует ли вообще разрешать пакеты параметров в сочетании с необязательными аргументами, но я бы на это не рассчитывал. - person Kyle Strand; 17.11.2017
comment
Кроме того, с C++ комитет, похоже, желает чрезвычайно гибкого синтаксиса, позволяющего все, что кажется, должно иметь какой-то смысл. Поскольку совершенно ясно, что означает вышеприведенная подпись, комитет не видел причин не разрешать ее. - person Kyle Strand; 17.11.2017
comment
Обратите внимание, однако, что требование, чтобы пакеты параметров располагались перед необязательными аргументами, не имеет смысла, поскольку не существует четкого правила того, как компилятор будет различать последний аргумент пакета параметров и необязательный аргумент. - person Kyle Strand; 17.11.2017
comment
@KyleStrand Да, мы (ну, по крайней мере, я ...) настолько внушены, чтобы думать, что, поскольку это входит в стандарт, для этого, вероятно, есть веская причина. Мне нравятся ваши рассуждения о пакете параметров. Так что, по сути, дело не столько в том, что аргумент по умолчанию не является последним, сколько в том, что пакет параметров должен быть последним. Это имеет смысл для меня. - person cantordust; 17.11.2017

В дополнение к отличному ответу rsp также стоит отметить, что такое поведение имеет логический смысл. Аргументы не по умолчанию, не входящие в пакет параметров, не могут следовать за аргументом по умолчанию, не приводя к требованию, чтобы аргумент по умолчанию был указан — в этом случае он больше не является аргументом по умолчанию.

Например, если бы было разрешено следующее:

void example(int x=0, int y);

Второй аргумент, отличный от значения по умолчанию, будет означать, что вызов функции должен быть структурирован example(1, 2);, поскольку первый параметр не может быть установлен по умолчанию. Это не относится к пустому пакету параметров. Рассмотрим следующую функцию:

template <typename... T> void example(int x = 0, T&&... t);

В этом случае все еще возможно установить x по умолчанию, вызвав example();

person AzCopey    schedule 16.11.2017
comment
Более того, void example(int x=0, int y); допускается иногда разрешено: это разрешено, если в предыдущем объявлении уже установлено значение по умолчанию для y. Это соответствует остальной части вашего объяснения: это единственный способ, которым можно использовать значение по умолчанию для x. - person ; 16.11.2017

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

person Gem Taylor    schedule 16.11.2017