2017-02-16 23 views
-1

Я создаю класс связанного списка, который использует внутренний класс Link и класс шаблона для определения типов, которые могут быть сохранены в связанном списке.Инициализация переменной шаблона для связанного списка

Однако в моем методе popValue, который должен возвращать шаблон типа T, я не могу инициализировать тип по умолчанию (в данном случае, под названием Point), несмотря на то, что тип хранится в каждом звене имеет конструктор по умолчанию - который в соответствии с these questions, указывает, что T retval = T()/T{} должен работать.

Кроме того, я не вижу, как соответствует сообщение об ошибке, учитывая, что T retval не является ссылочным типом?

Следовательно, рассматриваемый метод:

template<typename T> 
T LinkedList<T>::popValue() { 
    T retval = T(); //This doesnt work 
    Point test = Point(); //But this is allowed? 
    if (head != 0) { 
     Link *n = head; 
     retval = head->value; 
     head = head->next; 
     delete n; 
    } 
    return retval; 
} 

дает следующую ошибку value-initialization of reference type 'Point&':

enter image description here

Как я могу инициализировать эту переменную шаблона значение по умолчанию, так что если есть нет элементов в LinkedList, это значение по умолчанию можно вернуть, учитывая, что методы, описанные в других вопросах, похоже, не работают?

Большое спасибо,

Дэвид

EDIT

Из комментариев, я смотрел на специализации LinkedList.h и обнаружил, что я сделал большую ошибку, чтобы использовать его в качестве LinkedList<Point&> list;. При использовании в форме шаблона это означает, что T пытается создать экземпляр ссылочного типа - что недопустимо.

Для справки, я включил краткий код список того, что я думал, буду соответствующий код (но удалил недостоверные включают в себя, охрану и пространства имен для краткости) ...:

LinkedList.h

template<typename T> 
    class LinkedList { 
    public: 
     struct Link { ///< Struct inside the class LinkedList 
      Link(T val): value(val), next(0){}; 
      T value; 
      Link *next; 
      ~Link() { 
       delete next; 
      } //Iteratively delete 
     }; 
     T popValue(); ///< returns first element and deletes Link. 
    private: 
     Link *head; // this is the private member variable. It is just a pointer to the first Node 
    }; 

#include "LinkedList.cpp" //Allows definition of template methods in .cpp file 

LinkedList.cpp (ошибочный метод только)

template<typename T> 
    T LinkedList<T>::popValue() { 
     T retval = T(); //This doesnt work 
     Point test = Point(); // But this does 
     if (head != 0) { 
      Link *n = head; 
      retval = head->value; 
      head = head->next; 
      delete n; 
     } 
     return retval; 
    } 
+0

Но тогда я мог бы использовать его для типа, который не является объектом «Point»? – davidhood2

+0

Не могли бы вы дать очень короткий ответ, чтобы показать, как это будет использоваться для LinkedList.h/.cpp (просто просто описание класса и конструктор или один метод будет в порядке)? – davidhood2

+2

Компилятор «LinkedList» инициализируется с помощью 'T = Point &'. Это явно не то, что вы хотите. Пожалуйста, опубликуйте [mcve]. –

ответ

1

В соответствии с сообщением об ошибке

value-initialization ссылочного типа «точка» &

Т весьма возможно ссылочный тип.

Вы можете проверить это:

static_assert(std::is_reference<T>::value == false, ""); 

С помощью std::remove_reference (std::decay также полезен в этом случае), вы можете получить тип называемый Т, который позволит вам определить бесспорного ссылочную переменную ,

#include <type_traits> 
int main() { 
    using T = int &; 
    std::remove_reference_t<T> b = std::remove_reference_t<T>(); 
    return 0; 
} 

В случае "x_t" не объявлен:

#include <type_traits> 
int main() { 
    using T = int &; 
    typename std::remove_reference<T>::type b = 
     typename std::remove_reference<T>::type(); 
    return 0; 
} 

Менее родственный:

"Сохранение" ссылка вызовет у вас много неприятностей, потому что обычно мы не» t проверить, ссылается ли ссылка на ничего, &ref != nullptr. И, скорее всего, вы не хотите реализовать popValue таким образом:

template<typename T> 
T LinkedList<T>::popValue() { 
    if (head != 0) { 
     Link *n = head; 
     T retval = head->value; 
     head = head->next; 
     delete n; 
     return retval; 
    } else { 
     std::remove_reference_t<T> x = std::remove_reference_t<T>(); 
     return x; // very bad when T is reference 
    } 
} 

тошав элемент выскочил на выходной параметр еще вариант (просто держать выходной параметр без изменений, если список пуст), но может быть, вы просто хотите не хранить ссылки.