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

时间:2014-04-24 05:55:58

标签: c++ node.js templates pointers

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

要从卷曲处理程序调用函数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),那个空指针会使节点脚本退出,代码为-1073741819。

将空字符串作为结果放在那里的解决方法是什么?

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 ++,所以请随意对代码做任何评论。


所以,在搜索之后,我发现了模板特化,因此为上面的函数创建了一个,但是,这基本上生成了两个具有几乎相同签名的函数,任何替代方案?

1 个答案:

答案 0 :(得分:1)

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

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 ) );
}

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


上面的代码仍然不满意,我在code review上寻求帮助,@michael-urman帮助我,使用traits类的专业化,我们走了:

// 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 ) );
}

没有重复!