Должны ли вариадические конструкторы скрывать неявно генерируемые?
Предполагается, что конструкторы с переменными координатами скрывают неявно сгенерированные, то есть конструктор по умолчанию и конструктор копирования?
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);
}
Снова обе строки напечатаны.
1 ответ
Объявление неявно объявленного конструктора копии фактически не подавляется. Это просто не вызывается из-за правил разрешения перегрузки.
Неявно объявленный конструктор копирования имеет вид Foo(const Foo&)
, Важной частью этого является то, что требуется постоянная ссылка. Ваш шаблон конструктора использует неконстантную ссылку.
a
не является константным, поэтому неконстантный пользовательский шаблон конструктора предпочтительнее неявно объявленного конструктора копирования. Чтобы вызвать неявно объявленный конструктор копирования, вы можете сделать a
Const:
const Foo a;
Foo b(a);
или вы можете использовать static_cast
чтобы получить постоянную ссылку на a
:
Foo a;
Foo b(static_cast<const Foo&>(a));
Правила разрешения перегрузки, которые описывают это, находятся в основном в §13.3.3.2/3 FCD C++0x. Этот конкретный сценарий с комбинацией ссылок lvalue и rvalue описан в различных примерах на стр. 303.
Шаблон конструктора variadic будет подавлять неявно объявленный конструктор по умолчанию, поскольку шаблон конструктора variadic объявлен пользователем, а неявно объявленный конструктор по умолчанию предоставляется только в том случае, если нет конструкторов, объявленных пользователем (C++0x FCD §12.1/5):
Если нет объявленного пользователем конструктора для класса
X
конструктор, не имеющий параметров, неявно объявляется как дефолтный.
Шаблон конструктора variadic не будет подавлять неявно объявленный конструктор копирования, поскольку только конструктор не шаблонов может быть конструктором копирования (C++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&&
и либо нет других параметров, либо все остальные параметры имеют аргументы по умолчанию.Если определение класса не объявляет явно конструктор копирования, и не существует объявленного пользователем конструктора перемещения, конструктор копирования неявно объявляется как дефолтный.