Iwakura Rein 2019-09-20 18:56 采纳率: 100%
浏览 480
已采纳

向函数模板中传入字符串,typeid()和if的搭配会失效,编译不通过,怎么办?

我写了个函数模板里用到了typeid,判断传入变量的类型。传入整型和浮点型都没问题,传入字符串直接编译不通过。

#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
struct Item
{
    int intvalue=0;
    double doublevalue=0.0;
    string stringvalue="";
};
template <typename T>
void TypeDetect(Item *p, T elem)
{
    if (*typeid(elem).name() == 'i')
        p->intvalue = elem;
    else if (*typeid(elem).name() == 'd')
        p->doublevalue = elem;
    else if (*typeid(elem).name() == 'P')
        p->stringvalue = elem;
}
int main()
{
    Item *p1 = new Item, *p2 = new Item, *p3 = new Item;
    TypeDetect(p1, 1);
    TypeDetect(p2, 1.1);
    TypeDetect(p3, "abc");
    cout << p1->intvalue << endl;
    cout << p2->doublevalue << endl;
    cout << p3->stringvalue << endl;
    return 0;
}

直接编译上述代码会报错:

invalid conversion from 'const char*' to 'int' [-fpermissive] [15, 21]
cannot convert 'const char*' to 'double' in assignment [17, 24]

但注释掉

TypeDetect(p3, "abc");

就可以编译运行了。这是为什么?传入字符串后typeid应该会判断它是一个指针,然后通过if语句判断,但似乎编译器就不认我写的三个if语句。

  • 写回答

1条回答 默认 最新

  • 斗酒神僧 2019-09-24 18:12
    关注

    1)判断expr1和expr2是否为同一类型,应使用typeid(expr1) == typeid(expr2)
    2)const char*代入函数模板TypeDetect变成了这样:

    void TypeDetect<const char*>(Item* p, const char* elem)
    {
        if (*typeid(elem).name() == 'i')
            p->intvalue = elem;
        else if (*typeid(elem).name() == 'd')
            p->doublevalue = elem;
        else if (*typeid(elem).name() == 'P')
            p->stringvalue = elem;
    }
    
    

    const char*类型变量elem被赋值给了int类型和double类型,这显然是不能通过编译的。为什么elem是int类型时,能通过编译呢?因为:(1)int允许隐式转换成double;(2)int类型赋值给string类型变量时,int先隐式转换成char, 然后调用string::operator=(char)。elem是double类型时,也是如此。
    3)建议修改类Item,参考下面的代码:

    struct Item_v2
    {
        int intvalue = 0;
        double doublevalue = 0.0;
        string stringvalue = "";
    
        void SetValue(int value)
        {
            intvalue = value;
        }
        void SetValue(double value)
        {
            doublevalue = value;
        }
        void SetValue(const char* value)
        {
            stringvalue = value;
        }
    };
    
    int main()
    {
        Item_v2 item1, item2, item3;
        item1.SetValue(1);
        item2.SetValue(1.2);
        item3.SetValue("1.23");
    }
    
    

    上面的代码运用函数重载为Item_v2的成员函数SetValue提供了三个版本,编译器根据实参的类型选择调用正确的版本。如果要运用typeid确定参数的类型并赋值给Item_v2相应的成员变量,请参考下面的代码:

    template <typename T>
    static void TypeDetect_v2(Item_v2& item, T value)
    {
        void* pv = &value;
        if (typeid(value) == typeid(int))
            item.intvalue = *static_cast<int*>(pv);
        else if (typeid(value) == typeid(double))
            item.doublevalue = *static_cast<double*>(pv);
        else if (typeid(value) == typeid(const char*))
            item.stringvalue = *static_cast<const char**>(pv);
    }
    void TypeDetect_Example()
    {
        Item_v2 item1, item2, item3;
        TypeDetect_v2(item1, 1);
        TypeDetect_v2(item2, 1.2);
        TypeDetect_v2(item3, "1.23");
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?