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

Aam*_*mir 5 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; 
}
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)

  • 如果要为没有类型的类型返回奇异值,则必须使用可选或等效的类型.如果您无法访问boost,您仍然可以定义你的(用于它的另一个常用名称是Fallible). (4认同)
  • 我没有使用boost,所以不能使用boost :: none (2认同)

unw*_*ind 9

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

  • 定义是正确的0,所以没有实际的收益[还有更多的类型]
  • 它是一个宏,在C++中最好避免使用宏

该页面的建议是:

  • 使用plain 0,或(对于C++ 0xwhatever)nullptr.

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

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

  • 为什么不使用NULL?对我而言,你正在处理指针iso更清楚.那样整数. (5认同)
  • NULL的使用与否是紧接在curcly括号位置旁边的编码样式或者在缩进时使用的空格数.我已经使用了两者,只要一贯使用,我就不喜欢一个.两种方式都存在争议,我觉得我听不到任何令人信服的说法. (3认同)
  • @Kristof:Stroustrup提出了一个相当边缘的论据 - http://www.research.att.com/~bs/bs_faq2.html#null (2认同)

sbi*_*sbi 7

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

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

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


Mot*_*tti 2

大多数类型都是默认可构造的,您有一个可以专门化的特征模板类(默认返回默认初始化对象)。

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)