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

Предполагается ли, что конструкторы вариации скрывают неявно сгенерированные?

Предполагается ли, что конструкторы Variadic скрывают неявно сгенерированные, т.е. конструктор по умолчанию и конструктор копирования?

struct Foo
{
    template<typename... Args> Foo(Args&&... x)
    {
        std::cout << "inside the variadic constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

Как-то я ожидал, что это ничего не опубликует после чтения этого ответа, но он печатает inside the variadic constructor дважды в g++ 4.5.0:( Правильно ли это поведение?


Это также происходит без вариационных шаблонов:

struct Foo
{
    Foo()
    {
        std::cout << "inside the nullary constructor\n";
    }

    template<typename A> Foo(A&& x)
    {
        std::cout << "inside the unary constructor\n";
    }
};

int main()
{
    Foo a;
    Foo b(a);
}

Снова распечатываются обе строки.

4b9b3361

Ответ 1

Объявление неявно объявленного конструктора копирования фактически не подавляется. Это просто не вызвано из-за правил разрешения перегрузки.

Неявно объявленный конструктор копирования имеет форму Foo(const Foo&). Важной частью этого является то, что он принимает ссылку на const. Ваш шаблон конструктора принимает неконстантную ссылку.

a не является константой, поэтому шаблон конструктора, не поддерживающий пользователя, является предпочтительным по сравнению с неявным объявлением конструктора копирования. Чтобы вызвать неявно объявленный конструктор копирования, вы можете сделать a const:

const Foo a;
Foo b(a);

или вы можете использовать static_cast для получения ссылки const на a:

Foo a;
Foo b(static_cast<const Foo&>(a));

Правила разрешения перегрузки, описывающие это, находятся в основном в §13.3.3.2/3 CCD 0x FCD. Этот конкретный сценарий с комбинацией ссылок lvalue и rvalue описывается различными примерами на стр. 303.


Шаблон конструктора Variadic будет подавлять неявно объявленный конструктор по умолчанию, потому что шаблон конструктора Variadic объявляется пользователем и неявно объявленный конструктор по умолчанию предоставляется только в том случае, если нет конструкторов, объявленных пользователем (С++ 0x FCD §12.1/5 ):

Если конструктор класса X не объявлен пользователем, конструктор, не имеющий параметров, неявно объявляется как дефолт.

Шаблон конструктора Variadic не будет подавлять неявно объявленный конструктор копирования, потому что конструктор копирования может быть конструктором без шаблонов (С++ 0x FCD §12.8/2, 3 и 8):

Конструктор без шаблона для класса X является конструктором копирования, если его первый параметр имеет тип X&, const X&, volatile X& или const volatile X&, и либо нет других параметров, либо все другие параметры имеют аргументы по умолчанию.

Конструктор без шаблона для класса X является конструктором перемещения, если его первый параметр имеет тип X&&, const X&&, volatile X&& или const volatile X&&, и либо других параметров нет, либо нет. все остальные параметры имеют аргументы по умолчанию.

Если определение класса явно не объявляет конструктор копирования и не существует объявленного конструктором перемещения, конструктор копирования неявно объявляется как дефолт.