如何从模板类中的方法返回NULL

时间:2009-09-08 09:09:15

标签: c++ templates

我有一个看起来像这样的方法:

template <typename T>
T Test<T>::FindItem(T item)
{
    if(found)
        //return original value, no problem here
    else
        //I want to return NULL here, like:
        return NULL; 
}

在某些情况下,这在运行时失败,因为某些值无法在C ++中转换为NULL,例如std::string。我应该采用什么方法?

9 个答案:

答案 0 :(得分:14)

如果你想按值返回并且不想弄乱返回指针和new / delete,你可以这样做:

template <typename T>
boost::optional<T> Test<T>::FindItem(T item)
{
    if(found)
        //return original value
    else
        return boost::none; 
}

并以这种方式使用它:

Test<int> var;
boost::optional<int> V = var.FindItem(5)

if (V)
{
    // found
    int val = *V;
}
else
{
    // not found
}

答案 1 :(得分:9)

Here,Stroustrup在C ++中给出了一些避免NULL的论据:

  • 定义只是0,所以没有实际的收益[还有更多要输入]
  • 这是一个宏,在C ++中最好避免使用宏

该页面的建议是:

  • 使用普通0或(对于C ++ 0xwhatever)nullptr

其次,如果要将无效指针作为失败信号返回,则需要将该函数声明为返回指向类型的指针,而不是类型本身。

第三,大多数标准库find()函数返回迭代器,而不是直接返回元素。这使您有可能以不同的方式实现“无法找到”的情况。

答案 2 :(得分:7)

您有一个可能返回有效对象的函数,但也指示不存在有效对象。结合所有可能的对象值有效的情况,这是find函数的设计问题。 (即使你调整了这个函数,例如,如果没有找到一个空字符串,它会如何与成功找到一个空字符串区别开来?)

随着时间的推移,发现了摆脱这种困境的几种方法。因此,您可以返回指针/迭代器,而不是返回实际值。然后NULL指针/结束迭代器将指示“未找到”。或者您可以通过非const引用获取值,将结果分配给它并通过返回的布尔值指示成功/失败。或者采取此处发布的其他解决方案之一。但是所有都需要你改变函数的界面 - 因为它有一个设计错误。

无论如何,在你跳入并执行此操作之前,你应该问问自己为什么要编写自己的容器/算法而不是使用std lib中的一个。

答案 3 :(得分:2)

你应该返回T * non T

答案 4 :(得分:2)

也许我太简单了,但我更喜欢只返回bool

template <typename T>
bool Test<T>::FindItem(T item)
{
    if (!found)
        return false;    
    item = <found item>;        
    return true; 
}

答案 5 :(得分:1)

大多数类型都是默认构造的,你有一个特殊的traits模板类(默认返回一个默认的初始化对象)。

template <class T>
struct Make {
    static T Default()
    {
         return T();
    }
};


class not_default_constructable {
public:
    explicit not_default_constructable(int i) {}
};

// specialize for not_default_constructable     
template <>
struct Make <not_default_constructable> {
    static not_default_constructable Default()
    {
         return not_default_constructable(42);
    }
};

答案 6 :(得分:1)

如果找不到,可以抛出异常。

由于您不了解要查找和返回的类型,因此您无法将该类型的任何特定值指定为错误代码。实质上,您试图将类型的完整域和错误值压缩到该类型的域中。

使用迭代器或其他包装器的建议有助于通过扩展返回类型的域来包含错误值来解决问题,但是如果你想坚持你正在处理的实际类型,那么异常是你最好的选择。这就是他们的目的。

答案 7 :(得分:0)

返回T()。如果T的类型为sometype *,则它将初始化为空指针。如果T的类型为sometype,则它将返回使用默认构造函数创建的对象,这应该足够(std::string将为空,整数类型如int s将是0等。)

答案 8 :(得分:0)

在我看来,你试图通过尝试返回NULL值来使自己复杂化......

而是做类似的事情:

class SomeError
{};
template <typename T>
    T Test<T>::FindItem(T item)
    {
        if(found) 
            //return original value, no problem here
        else
            throw(SomeError);
    }

投掷一个空课不需要任何费用......