初始化链表的模板变量

Initializing template variable for a linked list

我正在创建一个链表 class,它使用内部 Link class 和模板 class 来定义可以存储在链表。

但是,在我的方法 popValue 中,应该 return 模板类型 T,我无法初始化默认类型(在本例中,称为 Point),尽管事实上,存储在每个 Link 中的类型都有一个默认构造函数——根据 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&':

如何将这个模板变量初始化为默认值,这样如果 LinkedList 中没有元素,这个默认值可以被 returned,给出概述的方法在其他问题中似乎不起作用?

非常感谢,

大卫

编辑

从评论中,我查看了 LinkedList.h 的专业化,发现我犯了一个主要错误,将它用作 LinkedList<Point&> list;。 当以模板形式使用时,这意味着 T 正在尝试实例化引用类型 - 这是不允许的。

作为参考,我列出了我认为相关代码的简明代码清单(但为简洁起见删除了不重要的包含、保护和命名空间)...:[=​​25=]

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

根据报错信息

value-initialization of reference type 'Point&'

T 很可能是引用类型。

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

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

通过使用std::remove_reference (std::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;
}

不太相关:

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

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