如何让模板get函数处理string用getline,处理int保持原有输入行为?
Hey there! Let's work through fixing your get<T> function to handle int and string types exactly how you want. The problem with using typeid here is that it relies on runtime checks, but we can use C++'s compile-time features like template specialization or function overloading to solve this cleanly and efficiently.
Method 1: Template Specialization
Template specialization lets you write a custom implementation for a specific type while keeping the generic template for all others. Here's how to set it up:
First, define the generic template for most types (matches your original behavior):
#include <iostream> #include <string> using namespace std; template<typename T> T get(const string &prompt) { cout << prompt; T ret; cin >> ret; return ret; }
Then, add a specialized version for string that uses getline:
// Specialized implementation for string type template<> string get<string>(const string &prompt) { cout << prompt; string ret; // Critical: Skip leftover newline from previous input (like after cin >> int) if (cin.peek() == '\n') { cin.ignore(); } getline(cin, ret); return ret; }
Why the ignore()?
If you first use get<int>() and then get<string>(), the cin >> int leaves a newline character in the input buffer. Without ignore(), getline would read that empty newline as a blank string. The cin.peek() check ensures we only ignore when there's a newline waiting.
Method 2: Function Overloading
Another straightforward approach is to create non-template overloads for int and string—these will take priority over the generic template when called with those types:
#include <iostream> #include <string> using namespace std; // Overload for int (keeps your original cin >> behavior) int get(const string &prompt) { cout << prompt; int ret; cin >> ret; return ret; } // Overload for string (uses getline for full input) string get(const string &prompt) { cout << prompt; string ret; if (cin.peek() == '\n') { cin.ignore(); } getline(cin, ret); return ret; } // Generic template for all other data types template<typename T> T get(const string &prompt) { cout << prompt; T ret; cin >> ret; return ret; }
This works because when you call get<int>("Enter a number:"), the non-template overload is a better match than the generic template. Same logic applies to string.
Why typeid Didn't Work (And Why to Avoid It Here)
Using typeid inside the generic template relies on runtime checks, which is less efficient and not idiomatic for this scenario. Plus, typeid(T).name() returns a compiler-specific string (like "int" or "std::basic_string
Example Usage
int main() { int num = get<int>("Enter an integer: "); cout << "You entered: " << num << endl; string str = get<string>("Enter a string (with spaces): "); cout << "You entered: " << str << endl; double dbl = get<double>("Enter a double: "); cout << "You entered: " << dbl << endl; return 0; }
This will correctly read integers with cin >>, strings with spaces using getline, and other types with the generic cin >> behavior.
内容的提问来源于stack exchange,提问作者SKREFI

