【问题标题】:How do I best handle conversion into template type from const char *如何最好地处理从 const char * 转换为模板类型
【发布时间】:2021-05-08 21:08:21
【问题描述】:

我有一个模板函数,我需要在其中将 const char * 转换为我的模板值。 我知道这个 const char * 最初是从 ascii 文本文件中读取的。我当前的代码如下所示:


    template <typename T>
    bool Get(T &value, std::string const &query, T const &default)
    {
        const char* result = DataHandler.GetValue(query);
        if (result != NULL)
        {
            value = static_cast<T>(result); //Here is the issue
            return true;
        }
        value = default
        return false;
    }

以 int 为例,我得到了错误

错误 C2440:“static_cast”:无法从“const char *”转换为“int”

有没有办法可以无缝地将 char* 转换为我的类型 T,我在 SO 上找不到答案。

在最坏的情况下,我可以为我期望的 10 种类型提供一个案例,如果不是其中一种,我会给出错误,但如果可能的话,我宁愿不这样做。

【问题讨论】:

  • 添加一个专门针对您支持的每种类型的转换函数。
  • 转换字符串有多种解释,例如可以将“0xFF”转换为255,或者不支持十六进制。您需要决定支持哪些并将其添加(有一些可爱的标准函数,如 atoi 可以提供帮助)
  • 这个字符串中有什么数据?键入数字的ASCII表示?原始值的按位复制?您是否将文本Stairway to Heaven 转换为 MP3?没有一种方法可以将“ASCII”转换为任意对象类型。这个问题不够清晰。
  • 处理此问题的一般方法是将转换模板化并将其添加为模板参数,将该参数默认为合理的值,并在您想做一些深奥的事情时进行自定义。此外,您的函数返回bool,因此返回truefalse 更清晰,而不是10

标签: c++ templates type-conversion


【解决方案1】:

有没有办法可以无缝地将 char* 转换为我的类型 T,

没有。

没有办法使从字符串到类型的转换自动适用于所有类型。必须为每个类实现这种转换。通常,它是通过为std::istream 实现流提取运算符&gt;&gt; 来完成的。 int 等内置类型和std::string 等一些标准类型已经有了这样的操作符。然后你可以这样做:

std::istringstream istream(result);
int i;
istream >> i;

【讨论】:

    【解决方案2】:

    在不确切知道您要什么的情况下,使用@eerorika 给出的答案,这是一种进行转换的通用方法:

    #include <sstream>
    #include <string>
    #include <iostream>
    
    template <typename T>
    struct DefaultConverter
    {
        static T Convert(const char *result)
        {
           std::istringstream istream(result);
           T i;
           istream >> i;        
           return i;
        }
    };
    
    template <typename T, typename Converter = DefaultConverter<T>>
    bool Get(T &value, std::string const &query, T const &defaultVal)
    {
        const char* result = "100";
        value = Converter::Convert(result); 
        return true;
    }
    
    int main()
    {
        int test = 10;
        Get(test, "abc123", test);
        std::cout << test;
    }
    

    引用DataHandler 函数的代码对于说明上述内容并不重要。

    基本上,Get 函数需要一个附加参数,即具有可用Convert 函数的转换模板,该函数可由Get 调用。请注意,默认转换器仅使用@eeerorika 给出的先前答案中所示的代码。

    这使您可以灵活地提供自己的转换器,该转换器具有Convert 函数,可以执行任何自定义操作。

    例如:

    struct SomeMPEGObject
    {
        SomeMPEGObject() {}
        SomeMPEGObject(const char *) {}
    };
    
    struct MPEGConverter
    {
        static SomeMPEGObject Convert(const char *result)
        {
           return SomeMPEGObject(result);
        }
    };
    //...
    
    SomeMPEGObject mpeg;
    Get<SomeMPEGObject, MPEGConverter>(mpeg, "12345", mpeg);
    

    这无需更改Get 函数中的任何代码即可工作。

    【讨论】:

    • 这看起来很不错,有没有什么地方可以查到哪些类型已经实现了 >> 运算符,哪些类型需要重载/提供我自己的转换器?
    • 让编译器完成这项工作。如果类型有operator &gt;&gt; ok,如果没有,那么编译器会报错。
    • 这个想法是应该记录 Get 函数,默认将在类型上调用 &gt;&gt; 以及任何自定义(或者如果类型没有 &gt;&gt; 重载),然后提供自定义转换类型。这与std::sort 要求您的类型默认具有&lt; 可用,或者如果没有,则使用描述排序标准的lambda 或函数对象/函数没有什么不同。另一种变体是创建两个Get 函数,一个自动为&gt;&gt; 工作,另一个需要指定转换函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 2018-11-16
    • 1970-01-01
    相关资源
    最近更新 更多