初始化链表的模板变量

时间:2017-02-16 22:23:22

标签: c++ templates constructor initialization

我正在创建一个链表类,它使用内部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中没有元素,则可以返回此默认值,前提是其他问题中概述的方法似乎不起作用?

非常感谢,

大卫

修改

通过评论,我查看了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;
    }

1 个答案:

答案 0 :(得分:1)

根据错误消息

  引用类型“Point&amp;”

value-initialization

T很可能是参考类型。

您可以通过以下方式查看:

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

通过使用std::remove_referencestd::decay在这种情况下也很有用),您可以获得T引用的类型,这将使​​您能够定义非引用变量。

#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;
}

不太相关:

“存储”引用会给您带来很多麻烦,因为通常我们不会检查引用是否引用任何内容,&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
    }
}

返回由output参数弹出的元素仍然是一个选项(只要在列表为空时保持输出参数不变),但也许你只想存储没有引用。