C++:是否可以创建返回null的模板函数

C++: is it possible to create template function returning null?

本文关键字:null 函数 返回 创建 是否 C++      更新时间:2023-10-16

我有一个可以返回不同类型的模板函数。

template <class typ>
typ GetRespVal_byField(const std::string & _fname){
for (pqxx::result::const_iterator row = m_result.begin();
     row != m_result.end();
     ++row)
    {
        if (!row[_fname].is_null())
            return row[_fname].as<typ>();
        else
            return NULL; //this is what i want 
    }
}

这是一个正确的实施吗?

只要typ可以取NULL值(或者如果typ对象可以由NULL值构造),是的,你可以。例如,如果type是指针或int

您甚至可以返回foo_bar。。。。如果foo_bar是有效的typ值,它将起作用。。。。

模板解析是在编译时完成的,因此,正如YSC所评论的,如果它进行编译,那么是的,在类型检查方面是允许的(现在,代码编译并不一定意味着它会在运行时工作,但对于您的特定问题,它已经足够好了)。。。。

是否可以创建返回null的模板函数?

一般来说,是的,当然。为什么模板函数不能做到这一点?

然而。。。

这是一个正确的实施吗?

这取决于您对"正确"的定义:)

例如,如果您试图用std::stringtyp实例化函数,那么返回NULL会调用未定义的行为(因为您将尝试从空指针构造std::string)。不明确的行为通常被认为是非常不正确的。

考虑Boost。可选作为表示某个事物不存在的替代方案。它比NULL更通用。

这是可能的,但可能并不总是一个好主意。例如,如果typstring,那么您的代码将进行编译,因为NULL将被解释为char *,从中隐式构造字符串。然而,当else分支被命中时,代码将在运行时失败,因为尝试从NULL构造字符串是未定义的行为,几乎肯定会导致访问冲突。

因此,我建议至少对您的代码进行两项改进。

  1. 将类型特征与static_assert结合使用,以确保typ是指针类型。将此添加到您的模板功能中:

    static_assert(is_pointer<typ>::value, "<typ> must be a pointer type");
    

    这排除了不是指针但可以从指针构造的类型,并使错误消息对用户更加清晰。

  2. 返回nullptr而不是NULL-主要是为了使意图更明确,但也为了避免转换为整型会是坏事的假设场景(与NULL不同,nullptr不是隐式转换为整型)。

更普遍地说,编译模板并没有多大作用。微软最近才放弃了一种可以粗略地称之为模板文本替代实现的东西:

选择实现这个[模板,在旧编译器中]的方法是对一个模板,然后将整个模板捕获为一个令牌字符串(这与编译器中处理宏的方式非常相似)稍后,当模板被实例化时,该令牌流将通过解析器重播,并且模板参数将被替换。

之所以放弃它,是因为它不足以正确实现模板。但是C++中的模板在很大程度上仍然是语义意义上的模板,这就是为什么使用代码编译模板的常用方法需要有可用的模板源。

这与严格意义上编译独立模板的C#(当然是编译IL)形成了鲜明对比。

实例化模板做得更多:

#include<iostream>
using namespace std;
// this works;
template<typename T> T f(T t)
{
    return cout;
}       
// this doesn't 
// double  d = f(1.0);

您可以编写一个类型trait类,为您使用的任何类型定义NULL。我想你对此会有问题——你会为std::string指定什么NULL?您可以更改您的函数签名并返回std::pair<typ, bool>,其中:

  1. 如果返回非NULL值,则first等于返回值,second等于true
  2. 如果应返回NULL值,则第一个值等于默认的初始化类型,secondfalse