Można i tak... Jest oczywiście jeszcze kilka innych sposobów:
#include <iostream>
#include <limits>
#include <type_traits>
// Pasuje do: bool, char, char16_t, char32_t, wchar_t, short, int, long, long long...
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
readValue(const std::string& msg) {
T value;
for(;;) {
std::cout << msg;
std::cin >> value;
if(!std::cin) {
std::cerr << "Dane nieprawidłowe.\n"
<< "Spróbuj jeszcze raz.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
break;
}
}
return value;
}
// Pasuje do: float, double, ...
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
readValue(const std::string& msg) {
T value;
for(;;) {
std::cout << msg;
std::cin >> value;
if(!std::cin) {
std::cerr << "Dane nieprawidłowe.\n"
<< "Spróbuj jeszcze raz.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else {
break;
}
}
return value;
}
int main() {
auto value1 = readValue<unsigned>("Wprowadź dane bez znaku: ");
std::cout << "Wprowadzono i przyjęto: " << value1 << '\n';
auto value2 = readValue<int>("Wprowadź dane ze znakiem: ");
std::cout << "Wprowadzono i przyjęto: " << value2 << '\n';
auto value3 = readValue<float>("Wprowadź zmiennoprzecinkowe: ");
std::cout << "Wprowadzono i przyjęto: " << value3 << '\n';
}
Testów std::is_* jest w <type_traits> wiele...