将类型标识与模板一起使用

Using typeid with templates

本文关键字:一起 类型 标识      更新时间:2023-10-16
template<class T>
inline T Library<T>::get_isbn()
{
    T temp;
    cout << "Enter the name/no:" << endl;
    cin >> temp;
    string ka;
    if (typeid(temp) == typeid(ka))
    {
        while (islower(temp[0]))
        {
            cout << " Pls enter the using the first letter as capital" << endl;
            cin >> temp;
        }
    }
}
return temp;
}

我正在创建一个模板类,它可以将整数或string作为模板参数,当我创建T作为string的类对象时,它会进入循环并且一切正常。但是当我使用 int 作为模板参数创建一个对象时,它会给我以下两个错误:

错误

C1903:无法从以前的错误中恢复;正在停止 汇编

错误 C2228:".at"的左侧必须具有类/结构/联合

我希望如果传递的参数是string,那么只有检查第一个字母是大写的代码应该运行,否则当我将模板参数作为int时,它不应该检查第一个字母的东西。

C++中的if始终(语义上)是运行时决策。编译器可以在编译时对其进行评估,并丢弃未使用的分支。但这可能并不意味着它必须。您仍然必须确保所有分支都包含有效的代码。

在此示例中,temp如果表达式 temp[0] 是整数,则表达式的格式不正确。最简单的解决方案是在泛型函数中调用重载函数 - 注意:通过引入typeid分支,您的算法本质上不再是泛型的,它需要对某些类型进行特殊处理。

template<class T>
void get_isbn_impl(T&)
{
    // default implementation
}
void get_isbn_impl(string& str)
{
    // special version for `string`
    while (islower(str[0]))
    {
        cout << " Pls enter the using the first letter as capital" << endl;
        cin >> str;
    }
}
template<class T>
inline T Library<T>::get_isbn()
{
    T temp;
    cout << "Enter the name/no:" << endl;
    cin >> temp;
    get_isbn_impl(temp);
    return temp;
}

也可以专攻Library<string>(整个班级)或仅Library<string>::get_isbn

typeid 不是 constexpr,因此在编译阶段不会影响模板内容。所有的东西都必须编译。

C++ 17 引入了 if constexpr 语句,因此可以用类似于示例的方式定义函数:


#include <string>
#include <cctype>
#include <iostream>
#include <type_traits>
template<class T>
inline T get_isbn()
{
    T temp;
    std::cout << "Enter the name/no:" << std::endl;
    std::cin >> temp;
    std::string ka;
    // if (typeid(temp) == typeid(ka)) // It is not a constexpr.
    
    // if constexpr compiles only when condition is met.
    
    // Passing types directly to std::is_same
    // if constexpr (std::is_same<T, std::string>::value)
    
    // Deducing types using decltype()
    if constexpr (std::is_same<decltype(temp), decltype(ka)>::value)
    {
        while (std::islower(temp[0]))
        {
            std::cout << " Pls enter the using the first letter as capital" << std::endl;
            std::cin >> temp;
        }
    }
    return temp;
}
int main()
{
    const auto isbn_int = get_isbn<int>();
    std::cout << "The ISBN<int> is: ["<< isbn_int << "]" << std::endl;
    
    const auto isbn_string = get_isbn<std::string>();
    std::cout << "The ISBN<string> is: ["<< isbn_string << "]" << std::endl;
    return 0;
}
// Sample input/output:
// Enter the name/no:
// 123
// The ISBN<int> is: [123]
// Enter the name/no:
// My-ISBN-Number 
// The ISBN<string> is: [My-ISBN-Number]

在 C++17 之前,您必须使用模板专用化,如@dyp所述。