我有一个看起来像这样的方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
这在某些情况下在运行时失败,因为某些值在C++中无法转换为NULL,例如,std::string.我应该遵循什么方法?
Xeo*_*eor 14
如果你想按值返回并且不想弄乱返回指针和new/delete,你可以这样做:
template <typename T>
boost::optional<T> Test<T>::FindItem(T item)
{
if(found)
//return original value
else
return boost::none;
}
Run Code Online (Sandbox Code Playgroud)
并以这种方式使用它:
Test<int> var;
boost::optional<int> V = var.FindItem(5)
if (V)
{
// found
int val = *V;
}
else
{
// not found
}
Run Code Online (Sandbox Code Playgroud)
在这里,Stroustrup给出了一些NULL在C++中避免的论据:
0,所以没有实际的收益[还有更多的类型]该页面的建议是:
0,或(对于C++ 0xwhatever)nullptr.其次,如果要将无效指针作为失败信号返回,则需要将该函数声明为返回指向类型的指针,而不是类型本身.
第三,大多数标准库find()函数返回迭代器,而不是直接返回元素.这使您有可能以不同的方式实现"无法找到"的情况.
您有一个可能返回有效对象的函数,但也指示不存在有效对象.结合所有可能的对象值有效的情况,这是find函数的设计问题.(即使你调整了函数,例如,如果没有找到一个空字符串,它会返回一个空字符串,如何区别于成功找到一个空字符串?)
随着时间的推移,发现了摆脱这种困境的几种方法.因此,您可以返回指针/迭代器,而不是返回实际值.然后NULL指针/结束迭代器将指示"未找到".或者您可以通过非const引用获取值,将结果分配给它并通过返回的布尔值指示成功/失败.或者采取此处发布的其他解决方案之一.但是所有都需要你改变函数的界面 - 因为它有一个设计错误.
无论如何,在你跳入并执行此操作之前,你应该问自己为什么要编写自己的容器/算法而不是使用std lib中的一个.
大多数类型都是默认可构造的,您有一个可以专门化的特征模板类(默认返回默认初始化对象)。
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);
}
};
Run Code Online (Sandbox Code Playgroud)