본문으로 건너뛰기 C++ Chrono Literals | 'Time Literals' Guide

C++ Chrono Literals | 'Time Literals' Guide

C++ Chrono Literals | 'Time Literals' Guide

이 글의 핵심

How to write duration readably with C++14 chrono literals (1s, 500ms, 2h, etc.). Covers std::chrono_literals, unit operations, and practical examples.

Introduction

C++14 chrono literals allow expressing time values concisely and readably. You can write 500ms instead of std::chrono::milliseconds(500).


1. chrono Literals Basics

Literal Types

#include <iostream>
#include <chrono>

using namespace std::chrono_literals;

int main() {
    // Time literals
    auto ns = 100ns;     // nanoseconds
    auto us = 100us;     // microseconds
    auto ms = 100ms;     // milliseconds
    auto s = 5s;         // seconds
    auto min = 10min;    // minutes
    auto h = 2h;         // hours
    
    std::cout << "5 seconds: " << s.count() << "s" << std::endl;
    std::cout << "10 minutes: " << min.count() << "min" << std::endl;
    std::cout << "2 hours: " << h.count() << "h" << std::endl;
}

Literal Types Table

LiteralTypeDescription
100nsstd::chrono::nanosecondsNanoseconds (10⁻⁹s)
100usstd::chrono::microsecondsMicroseconds (10⁻⁶s)
100msstd::chrono::millisecondsMilliseconds (10⁻³s)
5sstd::chrono::secondsSeconds
10minstd::chrono::minutesMinutes
2hstd::chrono::hoursHours

Key Concepts:

  • namespace: std::chrono_literals required
  • Type safety: Type checking at compile time
  • Readability: Clear and concise code

2. Time Operations

Basic Operations

#include <iostream>
#include <chrono>

using namespace std::chrono_literals;

int main() {
    // Addition
    auto total = 1h + 30min + 45s;
    
    // Subtraction
    auto diff = 2h - 30min;
    
    // Multiplication
    auto doubled = 5s * 2;
    
    // Division
    auto half = 10min / 2;
    
    // Comparison
    if (500ms < 1s) {
        std::cout << "500ms is shorter than 1 second" << std::endl;
    }
}

Unit Conversion

Here is the main implementation:

#include <iostream>
#include <chrono>

using namespace std::chrono_literals;

int main() {
    auto total = 1h + 30min + 45s;
    
    // Convert to seconds
    auto totalSeconds = std::chrono::duration_cast<std::chrono::seconds>(total);
    std::cout << "Total " << totalSeconds.count() << " seconds" << std::endl;
    // Output: Total 5445 seconds
    
    // Convert to milliseconds
    auto totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(total);
    std::cout << "Total " << totalMs.count() << "ms" << std::endl;
    // Output: Total 5445000ms
    
    // Convert to minutes (truncate decimal)
    auto totalMin = std::chrono::duration_cast<std::chrono::minutes>(total);
    std::cout << "Total " << totalMin.count() << " minutes" << std::endl;
    // Output: Total 90 minutes
}

3. Practical Examples

Example 1: sleep

#include <iostream>
#include <thread>
#include <chrono>

using namespace std::chrono_literals;

int main() {
    std::cout << "Start" << std::endl;
    
    // Old way (complex)
    // std::this_thread::sleep_for(std::chrono::seconds(2));
    
    // Using literals (concise)
    std::this_thread::sleep_for(2s);
    
    std::cout << "After 2 seconds" << std::endl;
    
    // Millisecond unit
    std::this_thread::sleep_for(500ms);
    std::cout << "After 0.5 seconds" << std::endl;
}

Example 2: Timeout

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

using namespace std::chrono_literals;

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::this_thread::sleep_for(1s);
    
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    
    cv.notify_one();
}

int main() {
    std::thread t(worker);
    
    std::unique_lock<std::mutex> lock(mtx);
    
    // Wait 500ms
    if (cv.wait_for(lock, 500ms, []{ return ready; })) {
        std::cout << "Ready" << std::endl;
    } else {
        std::cout << "Timeout (500ms)" << std::endl;
    }
    
    // Wait 2s
    if (cv.wait_for(lock, 2s, []{ return ready; })) {
        std::cout << "Ready" << std::endl;
    }
    
    t.join();
}

Example 3: Timer Class

#include <iostream>
#include <chrono>
#include <thread>

using namespace std::chrono_literals;

class Timer {
    std::chrono::steady_clock::time_point start;
    
public:
    Timer() : start(std::chrono::steady_clock::now()) {}
    
    // Check elapsed time
    template<typename Duration>
    bool elapsed(Duration timeout) const {
        auto now = std::chrono::steady_clock::now();
        return now - start >= timeout;
    }
    
    // Return elapsed time
    auto getElapsed() const {
        auto now = std::chrono::steady_clock::now();
        return now - start;
    }
    
    // Reset
    void reset() {
        start = std::chrono::steady_clock::now();
    }
};

int main() {
    Timer timer;
    int count = 0;
    
    // Work for 5 seconds
    while (!timer.elapsed(5s)) {
        std::this_thread::sleep_for(100ms);
        count++;
        
        if (count % 10 == 0) {
            auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
                timer.getElapsed()
            );
            std::cout << elapsed.count() << " seconds elapsed..." << std::endl;
        }
    }
    
    std::cout << "5 seconds elapsed, executed " << count << " times" << std::endl;
}

4. C++20 Date Literals

Using Date Literals

#include <iostream>
#include <chrono>

using namespace std::chrono;
using namespace std::chrono_literals;

int main() {
    // Date literals (C++20)
    auto year = 2026y;
    auto day = 29d;
    
    // Create date
    auto date = 2026y / March / 29d;
    
    std::cout << date << std::endl;
    // 2026-03-29
    
    // Combine time and date
    auto datetime = sys_days{2026y / March / 29d} + 14h + 30min;
}

Date Operations

#include <iostream>
#include <chrono>

using namespace std::chrono;
using namespace std::chrono_literals;

int main() {
    auto today = 2026y / March / 29d;
    
    // Date addition
    auto nextWeek = sys_days{today} + days{7};
    auto nextMonth = sys_days{today} + months{1};
    
    // Date difference
    auto date1 = sys_days{2026y / March / 1d};
    auto date2 = sys_days{2026y / March / 29d};
    auto diff = date2 - date1;
    
    std::cout << "Difference: " << diff.count() << " days" << std::endl;
    // Difference: 28 days
}

5. Common Issues

Issue 1: Missing namespace

#include <chrono>

int main() {
    // ❌ No namespace
    // auto sec = 5s;  // Compile error
    
    // ✅ Use namespace
    using namespace std::chrono_literals;
    auto sec = 5s;
    
    // ✅ Or explicit call
    auto sec2 = std::chrono_literals::operator""s(5);
}

Error message:

error: unable to find numeric literal operator 'operator""s'

Issue 2: Type Inference

#include <chrono>

using namespace std::chrono_literals;

int main() {
    // auto: accurate type inference
    auto ms = 100ms;  // std::chrono::milliseconds
    
    // Explicit type
    std::chrono::milliseconds ms2 = 100ms;
    
    // Implicit conversion
    std::chrono::seconds sec = 1000ms;  // 1 second
    
    // ❌ Precision loss
    // std::chrono::seconds sec2 = 1500ms;  // Compile error (1.5 seconds)
    
    // ✅ Use duration_cast
    auto sec3 = std::chrono::duration_cast<std::chrono::seconds>(1500ms);
    std::cout << sec3.count() << " seconds" << std::endl;  // 1 second (truncated)
}

Issue 3: Overflow

#include <chrono>
#include <iostream>

using namespace std::chrono_literals;

int main() {
    // ❌ Beware of large values (overflow possible)
    // auto days = 365 * 24h;  // int overflow
    
    // ✅ Use explicit type
    auto hours = std::chrono::hours(365 * 24);
    
    // ✅ Or use literal first
    auto oneDay = 24h;
    auto year = oneDay * 365;
    
    auto totalHours = std::chrono::duration_cast<std::chrono::hours>(year);
    std::cout << "1 year: " << totalHours.count() << " hours" << std::endl;
}

Issue 4: Mixed Operations

#include <chrono>
#include <iostream>

using namespace std::chrono_literals;

int main() {
    // Different unit operations (automatic conversion)
    auto total = 1h + 30min + 45s;
    
    // Automatically converted to smallest unit (seconds)
    std::cout << "Type: " << typeid(total).name() << std::endl;
    
    // Explicit conversion
    auto totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(total);
    std::cout << totalMs.count() << "ms" << std::endl;
    
    // Comparison operations (automatic conversion)
    if (500ms < 1s) {
        std::cout << "500ms is shorter than 1 second" << std::endl;
    }
}

6. Readability Improvement Patterns

Old Way vs Literals

#include <thread>
#include <chrono>

using namespace std::chrono_literals;

int main() {
    // ❌ Old way (hard to read)
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::this_thread::sleep_for(std::chrono::minutes(5));
    
    // ✅ Using literals (concise and clear)
    std::this_thread::sleep_for(500ms);
    std::this_thread::sleep_for(2s);
    std::this_thread::sleep_for(5min);
    
    // ❌ Complex calculation
    auto timeout = std::chrono::seconds(60 * 5);
    
    // ✅ Clear intent
    auto timeout2 = 5min;
    
    // ✅ Complex time expression
    auto duration = 1h + 30min + 45s;
}

Practical Usage

#include <iostream>
#include <chrono>
#include <thread>

// Import necessary modules
using namespace std::chrono_literals;

// Retry logic
template<typename Func>
bool retryWithTimeout(Func func, std::chrono::milliseconds timeout) {
    auto start = std::chrono::steady_clock::now();
    
    while (true) {
        if (func()) {
            return true;
        }
        
        auto elapsed = std::chrono::steady_clock::now() - start;
        if (elapsed >= timeout) {
            return false;
        }
        
        std::this_thread::sleep_for(100ms);
    }
}

int main() {
    int attempt = 0;
    
    bool success = retryWithTimeout([&]() {
        attempt++;
        std::cout << "Attempt " << attempt << std::endl;
        return attempt >= 3;  // Succeed on 3rd attempt
    }, 5s);
    
    if (success) {
        std::cout << "Success!" << std::endl;
    } else {
        std::cout << "Timeout" << std::endl;
    }
}

Summary

Key Points

  1. Literal types: ns, us, ms, s, min, h
  2. namespace: std::chrono_literals required
  3. Operations: Addition, subtraction, multiplication, division, comparison
  4. Conversion: Unit conversion with duration_cast
  5. C++20: Date literals (y, d)

chrono Literals Pros and Cons

ProsCons
Improved readabilityNamespace declaration required
Type safetyC++14 or higher required
Concise codeCaution with using in headers
Compile-time checkingBeware of large value overflow

Practical Tips

  1. namespace usage

    • Use using namespace only inside functions or cpp files
    • Use explicit calls in header files
  2. Type conversion

    • Beware of precision loss (1500msseconds)
    • Explicit conversion with duration_cast
  3. Performance

    • Literals processed at compile time
    • No runtime overhead

Next Steps



Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. How to write duration readably with C++14 chrono literals (1s, 500ms, 2h, etc.).

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers C++, chrono, literals, time, C++14.