C++로 재귀하면서 noexcept한 수치 입력 함수를 만든다
소개
C 언어로 안전하게 표준 입력으로부터 수치를 습득
라는 것을 썼는데 C++에서는 어떨까 봐 간다.
다행히 C와 달리 C++의 표준 입출력은 우수하다.
C++에서 숫자 입력의 열매에 흔한 예int input_num;
std::cin >> input_num;
C처럼 표준 입출력이 라스보스, 따위는 없다.
그러나 클래스에 대한 이해와 플래그에 대한 이해는 여전히 필요합니다.
C 언어로 안전하게 표준 입력으로부터 수치를 습득 에서 소개한 에러시는 재귀한다, 라고 하는 것은 실은 초보자에게도 알기 쉬운 것이 아닐까? 라고 생각하기 때문에 그것을 써 본다. 물론 예외라는 초보자에게는 잘 모르는 것은 의식하지 않고 끝나도록, noexcept
지정을 붙인다.
주의점
arithmetic에 한정
아리스-···가 아닌, arithmetic가 아닌 것에 대한 operator>>
가 불리지 않게, TMP로 연주할 필요가 있다. 물론 SFINAE를 사용한다. 방법은
std::enable_if를 사용하여 오버로드 할 때 enabler를 사용합니까?std::nullptr_t
형식을 사용하는 것을 사용합니다.
int8_t / uint8_t 형을 위해서
또 int8_t
/uint8_t
형은 일반적으로 char
/unsigned char
에 typedef 되고 있어 operator>>
있다.char
/singed shar
/unsigend char
형은 sizeof
연산자로 1이 되는 것을 이용해 쓰면 좋지만, 지금의 C++에는 static_if
와 같은 편리한 기능은 없기 때문에 TMP 할 필요가 있다.
이때 std::conditional
를 사용하면 매우 읽기 어려워지므로,
메모:std::conditional에서 if~else if~else 같은 것을 하려고 한다고 보기 어렵다
방법을 사용합니다.
아티팩트
#include <iostream>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include <limits>
/**
@brief \~japanese 複数条件のあるTMP用if
\~english multi-conditional if struct for TMP.
\~japanese std::enable_ifと組み合わせて使います。
\~english This class is used in conjunction with std::enable_if.
\~
@code
template<typename T>
using bar = first_enabled_t<
std::enbale_if<cond1, type1>,
std::enbale_if<cond2, type2>,
std::enbale_if<cond3, type3>,
default_type
>;
@endcode
*/
template<typename ...Args>
struct first_enabled {};
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<true, T>, Args...> { using type = T; };
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<false, T>, Args...> : first_enabled<Args...> {};
template<typename T, typename ...Args>
struct first_enabled<T, Args...> { using type = T; };
template<typename ...Args>
using first_enabled_t = typename first_enabled<Args...>::type;
//! for int8_t/uint8_t
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
using arithmetic_t = first_enabled_t <
std::enable_if<1 != sizeof(T), T>,
std::enable_if<std::is_signed<T>::value, int>,
unsigned int
>;
template<typename T_> using limit = std::numeric_limits<T_>;//create new type. C++11:alias declaration
/**
* @brief 標準入力から入力を受ける
* @details [long description]
*
* @param echo_str 入力を受ける前に表示する文字列。表示しない場合はnullptrか空白文字のみで構成された文字列へのポインタを渡す
* @param max 入力値を制限する。最大値を指定
* @param min 入力値を制限する。最小値を指定
* @return 入力した数字
* @exception none
*/
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>//Tが整数か浮動小数点型でないならばコンパイルエラーを出す
T input(const char* echo_str, const T max = limit<T>::max(), const T min = limit<T>::lowest()) noexcept {
arithmetic_t<T> buf;
try {
std::cin.exceptions(std::ios::failbit | std::ios::badbit);
if (nullptr != echo_str && '\0' != echo_str[0]) std::cout << echo_str << std::endl;//文字列が空じゃなければ出力
std::cin >> buf;//入力を受ける
if (max < buf || buf < min) throw std::out_of_range("input is iligal");//範囲チェック
}
catch (std::exception& er) {
std::cerr << er.what() << std::endl;//エラーメッセージ表示
return input("再入力してください。", max, min);//エラー時は再帰する方向で
}
return static_cast<T>(buf);
}
사용법
int main(){
const auto input1 = input("数字を1~50の間で入力してください", 50, 1);//input1はint型
const auto input2 = input("数字を1~50の間で入力してください", 50U, 1U);//input2はunsigned int型
const auto input3 = input<unsigned long long>("数字を1~50の間で入力してください", 1200, 3);//input3はunsigned long long型
const auto input4 = input<unsigned short>("数字を入力してください");//input4はunsigned short型
return 0;
}
결론
내부 실장은 예외를 남용한 것이 되어, 약간 무거울지도 모르지만, 원래 표준 입출력에 속도를 구해도 어쩔 수 없기 때문에 이것으로 좋다고 한다.
추가
잘 보면 이 녀석 bool에서도 움직인다···.
Reference
이 문제에 관하여(C++로 재귀하면서 noexcept한 수치 입력 함수를 만든다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/yumetodo/items/2a1d5f855bae6d100658
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
int input_num;
std::cin >> input_num;
arithmetic에 한정
아리스-···가 아닌, arithmetic가 아닌 것에 대한
operator>>
가 불리지 않게, TMP로 연주할 필요가 있다. 물론 SFINAE를 사용한다. 방법은std::enable_if를 사용하여 오버로드 할 때 enabler를 사용합니까?
std::nullptr_t
형식을 사용하는 것을 사용합니다.int8_t / uint8_t 형을 위해서
또
int8_t
/uint8_t
형은 일반적으로 char
/unsigned char
에 typedef 되고 있어 operator>>
있다.char
/singed shar
/unsigend char
형은 sizeof
연산자로 1이 되는 것을 이용해 쓰면 좋지만, 지금의 C++에는 static_if
와 같은 편리한 기능은 없기 때문에 TMP 할 필요가 있다.이때
std::conditional
를 사용하면 매우 읽기 어려워지므로,메모:std::conditional에서 if~else if~else 같은 것을 하려고 한다고 보기 어렵다
방법을 사용합니다.
아티팩트
#include <iostream>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include <limits>
/**
@brief \~japanese 複数条件のあるTMP用if
\~english multi-conditional if struct for TMP.
\~japanese std::enable_ifと組み合わせて使います。
\~english This class is used in conjunction with std::enable_if.
\~
@code
template<typename T>
using bar = first_enabled_t<
std::enbale_if<cond1, type1>,
std::enbale_if<cond2, type2>,
std::enbale_if<cond3, type3>,
default_type
>;
@endcode
*/
template<typename ...Args>
struct first_enabled {};
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<true, T>, Args...> { using type = T; };
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<false, T>, Args...> : first_enabled<Args...> {};
template<typename T, typename ...Args>
struct first_enabled<T, Args...> { using type = T; };
template<typename ...Args>
using first_enabled_t = typename first_enabled<Args...>::type;
//! for int8_t/uint8_t
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
using arithmetic_t = first_enabled_t <
std::enable_if<1 != sizeof(T), T>,
std::enable_if<std::is_signed<T>::value, int>,
unsigned int
>;
template<typename T_> using limit = std::numeric_limits<T_>;//create new type. C++11:alias declaration
/**
* @brief 標準入力から入力を受ける
* @details [long description]
*
* @param echo_str 入力を受ける前に表示する文字列。表示しない場合はnullptrか空白文字のみで構成された文字列へのポインタを渡す
* @param max 入力値を制限する。最大値を指定
* @param min 入力値を制限する。最小値を指定
* @return 入力した数字
* @exception none
*/
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>//Tが整数か浮動小数点型でないならばコンパイルエラーを出す
T input(const char* echo_str, const T max = limit<T>::max(), const T min = limit<T>::lowest()) noexcept {
arithmetic_t<T> buf;
try {
std::cin.exceptions(std::ios::failbit | std::ios::badbit);
if (nullptr != echo_str && '\0' != echo_str[0]) std::cout << echo_str << std::endl;//文字列が空じゃなければ出力
std::cin >> buf;//入力を受ける
if (max < buf || buf < min) throw std::out_of_range("input is iligal");//範囲チェック
}
catch (std::exception& er) {
std::cerr << er.what() << std::endl;//エラーメッセージ表示
return input("再入力してください。", max, min);//エラー時は再帰する方向で
}
return static_cast<T>(buf);
}
사용법
int main(){
const auto input1 = input("数字を1~50の間で入力してください", 50, 1);//input1はint型
const auto input2 = input("数字を1~50の間で入力してください", 50U, 1U);//input2はunsigned int型
const auto input3 = input<unsigned long long>("数字を1~50の間で入力してください", 1200, 3);//input3はunsigned long long型
const auto input4 = input<unsigned short>("数字を入力してください");//input4はunsigned short型
return 0;
}
결론
내부 실장은 예외를 남용한 것이 되어, 약간 무거울지도 모르지만, 원래 표준 입출력에 속도를 구해도 어쩔 수 없기 때문에 이것으로 좋다고 한다.
추가
잘 보면 이 녀석 bool에서도 움직인다···.
Reference
이 문제에 관하여(C++로 재귀하면서 noexcept한 수치 입력 함수를 만든다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/yumetodo/items/2a1d5f855bae6d100658
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
#include <iostream>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include <limits>
/**
@brief \~japanese 複数条件のあるTMP用if
\~english multi-conditional if struct for TMP.
\~japanese std::enable_ifと組み合わせて使います。
\~english This class is used in conjunction with std::enable_if.
\~
@code
template<typename T>
using bar = first_enabled_t<
std::enbale_if<cond1, type1>,
std::enbale_if<cond2, type2>,
std::enbale_if<cond3, type3>,
default_type
>;
@endcode
*/
template<typename ...Args>
struct first_enabled {};
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<true, T>, Args...> { using type = T; };
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<false, T>, Args...> : first_enabled<Args...> {};
template<typename T, typename ...Args>
struct first_enabled<T, Args...> { using type = T; };
template<typename ...Args>
using first_enabled_t = typename first_enabled<Args...>::type;
//! for int8_t/uint8_t
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
using arithmetic_t = first_enabled_t <
std::enable_if<1 != sizeof(T), T>,
std::enable_if<std::is_signed<T>::value, int>,
unsigned int
>;
template<typename T_> using limit = std::numeric_limits<T_>;//create new type. C++11:alias declaration
/**
* @brief 標準入力から入力を受ける
* @details [long description]
*
* @param echo_str 入力を受ける前に表示する文字列。表示しない場合はnullptrか空白文字のみで構成された文字列へのポインタを渡す
* @param max 入力値を制限する。最大値を指定
* @param min 入力値を制限する。最小値を指定
* @return 入力した数字
* @exception none
*/
template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>//Tが整数か浮動小数点型でないならばコンパイルエラーを出す
T input(const char* echo_str, const T max = limit<T>::max(), const T min = limit<T>::lowest()) noexcept {
arithmetic_t<T> buf;
try {
std::cin.exceptions(std::ios::failbit | std::ios::badbit);
if (nullptr != echo_str && '\0' != echo_str[0]) std::cout << echo_str << std::endl;//文字列が空じゃなければ出力
std::cin >> buf;//入力を受ける
if (max < buf || buf < min) throw std::out_of_range("input is iligal");//範囲チェック
}
catch (std::exception& er) {
std::cerr << er.what() << std::endl;//エラーメッセージ表示
return input("再入力してください。", max, min);//エラー時は再帰する方向で
}
return static_cast<T>(buf);
}
int main(){
const auto input1 = input("数字を1~50の間で入力してください", 50, 1);//input1はint型
const auto input2 = input("数字を1~50の間で入力してください", 50U, 1U);//input2はunsigned int型
const auto input3 = input<unsigned long long>("数字を1~50の間で入力してください", 1200, 3);//input3はunsigned long long型
const auto input4 = input<unsigned short>("数字を入力してください");//input4はunsigned short型
return 0;
}
결론
내부 실장은 예외를 남용한 것이 되어, 약간 무거울지도 모르지만, 원래 표준 입출력에 속도를 구해도 어쩔 수 없기 때문에 이것으로 좋다고 한다.
추가
잘 보면 이 녀석 bool에서도 움직인다···.
Reference
이 문제에 관하여(C++로 재귀하면서 noexcept한 수치 입력 함수를 만든다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/yumetodo/items/2a1d5f855bae6d100658
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
잘 보면 이 녀석 bool에서도 움직인다···.
Reference
이 문제에 관하여(C++로 재귀하면서 noexcept한 수치 입력 함수를 만든다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/yumetodo/items/2a1d5f855bae6d100658텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)