如何将模板变量更改为特定类型或不要让它成为空指针

How to change template variable to a specific type or don't let it become a null pointer

本文关键字:类型 空指针 变量      更新时间:2023-10-16

我正在为nodejs开发一个libcurl绑定,遇到了一个小障碍。

要从curl处理程序调用函数curl_easy_getinfo,我使用以下模板函数:

template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
    ResultType result;
    CURLINFO info = (CURLINFO) infoId;
    CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
    if ( code != CURLE_OK )
        return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
    return v8MappingType::New( result );
}

它的名字是这样的:

retVal = Curl::GetInfoTmpl<char*, v8::String>( *(obj), infoId );

来自libcurl文档:

CURLINFO_FTP_ENTRY_PATH

传递指向char指针的指针以接收指向字符串的指针保持进入路径的路径。这是libcurl的初始路径在登录到远程FTP服务器时结束这存储一个如果出现错误,则使用NULL作为指针(在7.15.4中添加)

自7.21.4 起也适用于SFTP

好的,如果我尝试从javascript land调用getInfo(CURLINFO_FTP_ENTRY_PATH),那么空指针将使节点脚本退出,代码为-103741819。

将空字符串作为结果放入其中的解决方法是什么?

template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
    ResultType result;
    CURLINFO info = (CURLINFO) infoId;
    CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
    //workaround for null pointer, aka, hack
    if ( infoId == CURLINFO_FTP_ENTRY_PATH && result == NULL ) {
        //what to place here to change result to an empty string?
       //this section is always going to be called only when ResultType = char*
    }
    if ( code != CURLE_OK )
        return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
    return v8MappingType::New( result );
}

我刚开始学习C++,所以可以随意对代码进行任何评论。


所以,在搜索之后,我发现了模板专业化,所以为上面的函数创建了一个,然而,这基本上生成了两个签名几乎相同的函数,有其他选择吗?

我学习了模板专业化,并用它来解决这个问题:

template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
    v8::HandleScope scope;
    ResultType result;
    CURLINFO info = (CURLINFO) infoId;
    CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
    if ( code != CURLE_OK )
        return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
    return scope.Close( v8MappingType::New( result ) );
}
template<> //template specialization
v8::Handle<v8::Value> Curl::GetInfoTmpl<char*,v8::String>( const Curl &obj, int infoId )
{
    v8::HandleScope scope;
    char *result;
    CURLINFO info = (CURLINFO) infoId;
    CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
    if ( !result ) { //null pointer
        return scope.Close( v8::String::New( "" ) );
    }
    if ( code != CURLE_OK )
        return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
    return scope.Close( v8::String::New( result ) );
}

代码大部分是重复的,但至少问题得到了解决。如果有人有更好的方法来解决这个问题,请随时发布。


我仍然对上面的代码不满意,我请求帮助进行代码审查,@michael urman帮助我完成了这项工作,在一个特质类上使用了专业化,我们开始了:

// traits class to determine whether to do the check
template <typename> struct ResultCanBeNull : std::false_type {};
template <> struct ResultCanBeNull<char*> : std::true_type {};
template<typename ResultType, typename v8MappingType>
v8::Handle<v8::Value> Curl::GetInfoTmpl( const Curl &obj, int infoId )
{
    v8::HandleScope scope;
    ResultType result;
    CURLINFO info = (CURLINFO) infoId;
    CURLcode code = curl_easy_getinfo( obj.curl, info, &result );
    // use the traits class to filter in or out the null pointer check
    if ( ResultCanBeNull<ResultType>::value && !result ) { //null pointer
        return v8::String::New( "" );
    }
    if ( code != CURLE_OK )
        return Curl::Raise( "curl_easy_getinfo failed!", curl_easy_strerror( code ) );
    return scope.Close( v8MappingType::New( result ) );
}

无重复!