2015-01-10 4 views
27

필자는 기억에 남는 방식으로 좋은 점을 설명하기 위해 우화적인 시간 단위 인 microfortnights을 사용하여 this excellent answer을 읽었습니다.커스텀 std :: chrono :: durations 및 std :: ratios를 형성하는 가장 좋은 방법은 무엇입니까?

typedef std::ratio<756, 625> microfortnights; 
std::chrono::duration<int, microfortnights> two_weeks(1000000); 

그리고 그 질문은 나에게 발생

난 정말 그런 프레임 동안 사용할 수있는 시간으로이 (가능성이 다른 아닌 사소한 기간을하고 싶어, 또는 N 사이클 동안 경우 프로세서), 이것을 수행하는 가장 좋은 방법은 무엇입니까?

나는 ratio<N, D>ND의 각 값과 관련된 고유 한 형식을 만들 것이다라는 것을 알고있다. 따라서 ratio<4, 6>은 (감소 된) 분수를 나타내더라도 ratio<2, 3>과 다른 유형입니다. 전환 비용을 줄이기 위해 전환 계수를 단순화하기 위해 항상 수학을 수행해야합니까?

이 쓸 더 편리 할 것입니다 :

using microfortnights = std::chrono::duration<long, ratio<86400*14, 1000000>>; 

대신 :

using microfortnights = std::chrono::duration<long, ratio<756, 625>>; 

을하지만이 대신 동일한 유형의 두 가지 유형이 될 것입니다. 첫 번째 표현은 정확성을 검사하는 것이 더 쉽습니다. 그러나이 분수에는 많은 표현이 있으며, 두 번째 표현은 틀림없이 표준이며 따라서 선호됩니다. 실제로 동일한 단위를 나타내는 프로그램에서 너무 많은 유형이 방황하면 불필요한 템플릿 코드가 부풀어 오를 수 있습니다.

+1

대신 질문 제목을'std :: ratio'에 대해 바꾸려면 괜찮습니까? 가장 중요한 주제는 선택된 예를 제외하고는 '크로노'와 거의 관련이없는 것처럼 보입니다. – sehe

+0

좋은 지적이 있습니다. 그러나 나는 '지속 기간'에 초점을 맞추기를 원한다. 그렇지 않으면 관객이 '비율'의 실제 적용을 보지 못할까봐 두려워한다. 제목에 '비율'을 추가하여 '비율'을 검색하면이 Q/A를보다 쉽게 ​​찾을 수 있습니다. –

+0

Hehe. +1 세트. (아이러니하게도, 이것이 실제로는 알 수없는 _microfortnight_ "오른쪽"을 만드는 것보다 실제로 더 관련이 있음을 알기까지는 시간이 걸렸습니다.) – sehe

답변

29

다음은 간략하게하기 위해 네임 스페이스를 무시합니다. duration은 네임 스페이스 std::chrono이고 ratio은 네임 스페이스 std입니다.

ratio이 산술을 직접 수행하지 않고도 최저 조건으로 감소되도록하는 두 가지 좋은 방법이 있습니다. 첫 번째는 매우 직접적 :

그냥 바로 microfortnights로 이동하려면,하지만 86,400 * 14/1,000,000의 감소 비율이 625분의 756 것을 파악하지 않고 직접 수립, 다만 ratio::type를 추가

using microfortnights = duration<long, ratio<86400*14, 1000000>::type>; 

모든 ratio<N, D>의 중첩이 typeNr/Dr가 감소하는 다른 분획 012,337,292,626,158이다 ratio<Nr, Dr>. N/D이 이미 감소 된 경우 ratio<N, D>::typeratio<N, D>과 동일한 유형입니다.사실, 내가 쓴 수, 이미 625분의 756 올바른 감소 부분을 것을 파악했다, 그러나 더 감소 될 수 있습니다 생각에 단지 편집증 :

using microfortnights = duration<long, ratio<756, 625>::type>; 

을 그래서 당신은 의심이있는 경우 귀하를 ratio은 가장 낮은 용어로 표시되거나 확인하는 데 신경 쓰고 싶지 않으므로 ratio 유형에 항상 ::type을 추가 할 수 있습니다.

사용자 정의 지속 시간 단위는 종종 가족의 한 부분으로 팝업 용장 배합. 그리고 전체 패밀리를 코드에 사용할 수있는 것이 편리합니다. 예를 들어 microfortnightsfortnights과 분명히 관련이 있으며, hours (또는 원하는 경우 seconds)에서 파생 된 days에서 파생 된 weeks과 관련이 있습니다.

한 번에 한 단위 씩 가족을 구성하면 가족 전체를 사용할 수있을뿐만 아니라 가장 단순한 변환으로 한 가족 구성원을 다른 가족 구성원과 연관시킴으로써 오류의 가능성을 줄일 수 있습니다. 또한 리터럴을 곱하는 대신 std::ratio_multiplystd::ratio_divide을 사용하면 ratio을 최하위 용어로 유지할 수 있도록 모든 문자를 ::type에 유지할 필요가 없습니다. 예를 들어

:

using days = duration<long, ratio_multiply<hours::period, ratio<24>>>; 

ratio_multiply 이미 최저 조건으로 감소 승산 결과에 의 typedef 이름이다.

using days = duration<long, ratio<86400>>; 

당신은 심지어 같은 번역 단위에서 모두 정의 할 수 있습니다, 당신은 재 정의 오류가 발생하지 않습니다 따라서 위는 동일한 유형입니다. 어떤 경우에도 당신은 지금 말할 수있다 :

using weeks   = duration<long, ratio_multiply<days::period,  ratio<7>>>; 
using fortnights  = duration<long, ratio_multiply<weeks::period,  ratio<2>>>; 
using microfortnights = duration<long, ratio_multiply<fortnights::period, micro>>; 

그리고 우리는 우리의 직접 배합에서와 동일한 유형입니다 microfortnights에 대한 형식 정의 이름으로 결국,하지만 훨씬 간단 일련의를 통해 한 전환 수. 우리는 분수를 최하위 용어로 줄이기 위해 고민 할 필요가 없습니다. 이제는 단 하나가 아닌 여러 유용한 단위가 있습니다.

std::ratio<1, 1000000> 대신 std::micro을 사용합니다. 이것은 부주의 한 오류를 피할 수있는 또 다른 장소입니다. 실수를 잘못 입력하고 잘못 읽는 것은 (적어도 나를 위해) 쉽습니다.