Нахождение typeid параметра шаблона - PullRequest
0 голосов
/ 20 апреля 2011

Оператор print в определении конструктора не печатается, разве конструктор не вызывает корректно в main?Я знаю, что здесь не хватает какой-то точки, пожалуйста, укажите.

#include <iostream>
#include <typeinfo>

template <typename T> class List
{
    public: 
        template <typename T2> List (List<T2> const&);
}; 

template <typename T> template <typename T2> List <T> :: List (List <T2> const&) 
{
    std :: cout << "\nType name:" << typeid (T2).name();
}

int main ()
{
    List <int> kk (List <int>);
    return 0;
}

Ответы [ 3 ]

6 голосов
/ 20 апреля 2011

В вашем коде есть пара неправильных вещей, о которых вы могли не знать.

List<int> kk( List<int> );

Эта строка не является определением переменной, а скорее объявлением функции, которая принимает List<int> в качестве аргумента и возвращает List<int>, так что фактически не будет вызываться никакой конструктор.Это называется most-vexing-parse (вы можете посмотреть его различные версии, выполнив поиск в SO или в разделе C ++ FAQ )

Вторая проблема заключается в том, что вы не можете создать ни один экземпляр экземпляра типа List, причина в том, что единственный предоставляемый вами конструктор - это шаблонный конструктор, который принимает в качестве аргумента второй List<U>.Это фактически отключает конструктор по умолчанию, поэтому единственный способ создать List<T> - это уже иметь List<U>, а это невозможно.Вы можете добавить конструктор по умолчанию обратно:

template <typename T>
class List {
public:
   List() {}
   template <typename U>
   List( List<U> const & ) {} // prefer const& as that will avoid unnecessary copying
};

И теперь вы можете написать:

List<int> l = List<int>(); // this will call List<int>::List( List<int> const & )

И, тем не менее, он по-прежнему не будет вызывать нужный вам конструктор.Причина немного неясна, но когда копирует конструирование элемента шаблона, компилятор не использует шаблонный конструктор.В приведенном выше коде он будет неявно определять конструктор копирования, выполняя для всех членов конструктор копирования методов и вызывая этот сгенерированный конструктор.Это означает, что в большинстве случаев, когда вы хотите предоставить шаблонный конструктор, вы также хотите предоставить не шаблонный конструктор копирования.

Чтобы вызвать этот конструктор, вам нужно будет предоставить другой тип:

List<int> l = List<double>();

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

2 голосов
/ 20 апреля 2011

А также «самый неприятный анализ», определенный Дэвидом:

  • вам нужен как минимум еще один конструктор для создания исходного объекта List, который будет передан конструктору копирования,
  • вам нужно изменить тип параметра, чтобы вызвать шаблонный конструктор копирования: как вы будете соответствовать неявно объявленному List(const List&) конструктору копирования.

Итак:

#include <iostream>

template <typename T>
struct X
{
    X() { std::cout << "X()\n"; }

    // implicitly like this anyway...
    // X(const X& rhs) { std::cout << "X(X&)\n"; }

    template <typename U>
    X(const U& u) { std::cout << "U\n"; }
};

int main()
{
    X<int> x;
    X<int> y(x);
}
1 голос
/ 20 апреля 2011

Что вы пытаетесь сделать с помощью этого оператора:

List <int> kk (List <int>);

(фактически он объявляет функцию и не может быть чем-то иным, кроме объявления функции.)

ДляПосмотрите выходные данные конструктора копирования, вы должны как-то вызвать конструктор копирования.Что означает наличие объекта для копирования.Это невозможно с указанным вами кодом: поскольку вы явно объявили конструктор, компилятор не предоставит конструктор по умолчанию, и у вас нет другого конструктора, с помощью которого можно создать объект.Таким образом, у вас нет возможности создавать что-либо для копирования.Если вы добавите

List() {}

в класс и напишите:

List<int> kk((List<int>());

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

List<int> a;
List<int> b(a);

Или просто поместите ваш вывод в конструктор по умолчанию.

...