Шаблон не может быть конструктором копирования.§12.8 / 2, сноска:
Поскольку конструктор шаблона никогда не является конструктором копирования, наличие такого шаблона не подавляет неявное объявление конструктора копирования.Конструкторы шаблона участвуют в разрешении перегрузки с другими конструкторами, включая конструкторы копирования, и конструктор шаблона может использоваться для копирования объекта, если он обеспечивает лучшее соответствие, чем другие конструкторы.
Поскольку аргумент вашего шаблона равен const &
, ее подпись будет точно такой же, как неявно объявленная функция в случае копирования, поэтому она никогда не будет использоваться в качестве конструктора копирования.
Это может быть нормально, потому что в примере, который вы используетеэто как преобразователь конструктор.Тем не менее, аргументы шаблона перед ::
представляют собой не выводимый контекст, поэтому компилятор не может подключить A<int>::B
и разрешить int
.Из-за различных способов специализации шаблонов у компилятора нет возможности выяснить, какой A
, если таковой имеется, отвечает требованиям.Вы можете добавить typedef A<int>::B B;
внутри A<float>
, и тогда int
и float
будут квалифицироваться как U
.
. Это можно исправить, используя SFINAE и добавляя типы членов в классы, чтобы помочьперемещаться по иерархии.Вот демоверсия .
#include <typeinfo>
#include <iostream>
template<typename T>
struct A
{
typedef T type;
struct B
{
B() {}
template<typename U>
B(const U& rhs, typename U::nest_A_parent * = NULL ) {
std::cout << "copied from type "
<< typeid( typename U::nest_A_parent::type ).name() << '\n';
}
private:
typedef A nest_A_parent;
template< typename U >
friend struct B;
};
};
int main()
{
A<int>::B x;
A<double>::B y( x );
}