模板变量的默认返回值

时间:2016-10-26 21:11:38

标签: c++ c++11 templates

我有一个模板链接列表实现,其中

T List<T>::GetElementFromHead()

从列表的头部返回值。列表为空时应返回什么值。

template <class T>
T List<T>::GetElementFromHead()
{
    T element;
    if (!IsEmpty())
    {
        element = Head->value;
    }
    return element;
}

如果IsEmpty()返回 true ,则return element;会抛出异常。

在这种情况下,如何返回null或空值?

1 个答案:

答案 0 :(得分:3)

  

列表为空时应返回什么值。

有两个合理的选择。

  1. 谁在乎呢。设置为GetElementFromHead()仅在列表不为空时才被调用的前提条件,然后您可以写:

    template <class T>
    T& List<T>::GetElementFromHead() {
        return Head->value;
    }
    

    这有几件好事。没有副本。它很快。如果我愿意,我可以修改值。没有额外的分支,因为您需要用户预先完成。无需担心错误的情况或提出合理的哨兵价值。如果您返回T{},如果Tint且该列表可能正常0,该怎么办?用户如何区分&#34;真实&#34; 0和&#34;假&#34; 0

    这就是标准库实现list::front()vector::front()等的方式。像标准库那样做通常是一个很好的决定。

  2. 封装返回值本身,无论它是否为实际值:

    template <class T>
    std::optional<T> List<T>::GetElementFromHead() {
        if (!IsEmpty()) {
            return Head->value;
        }
        else {
            return std::nullopt;
        }
    }
    

    (如果使用boost::optional,则最后一行应返回boost::none)。通过这种方式,返回值本身可以清楚地表明我们处于什么状态 - 我们要么拥有一个值,要么该值是列表的前面,或者我们没有值。再一次,没有必要提出哨兵。

    另一个版本是在失败时返回T*nullptr。这样做的好处是它不会产生副本或要求T可以复制构造。