본문으로 건너뛰기
Previous
Next
Boost Libraries for C++: Asio, Filesystem, Regex, DateTime,

Boost Libraries for C++: Asio, Filesystem, Regex, DateTime,

Boost Libraries for C++: Asio, Filesystem, Regex, DateTime,

이 글의 핵심

Complete Boost guide: Install with apt or vcpkg, use Boost.Asio for async I/O, Filesystem for portable paths, Regex for pattern matching, DateTime for calendar math, Program_options for CLI parsing, with real-world examples and production patterns.

Introduction: when the standard library is not enough

Boost fills gaps: Asio for async I/O, Regex when std::regex performance varies, DateTime for calendar math beyond chrono, Program_options for CLI parsing, and more. Many facilities later became std (optional, filesystem, etc.)—prefer std when it matches your standard level.

flowchart LR
  subgraph stdlib[Standard library]
    S1[vector, string]
    S2[optional C++17]
    S3[filesystem C++17]
  end
  subgraph boost[Boost]
    B1[Asio]
    B2[Beast]
    B3[Regex]
    B4[DateTime]
    B5[Program_options]
  end
  stdlib -->|gaps| boost
  boost -->|standardization source| stdlib

Requirements: C++14+, Boost 1.70+ typical for Asio/Beast samples.

Table of contents

  1. Installation
  2. Boost.Asio
  3. Boost.Filesystem
  4. Boost.Regex
  5. Boost.DateTime
  6. Boost.Program_options
  7. CMake integration
  8. Real-world examples
  9. Performance comparison
  10. Common errors
  11. Best practices
  12. Production patterns

1. Installation

apt (Ubuntu/Debian)

# All libraries
sudo apt-get install libboost-all-dev
# Specific components
sudo apt-get install \
    libboost-system-dev \
    libboost-filesystem-dev \
    libboost-regex-dev \
    libboost-date-time-dev \
    libboost-program-options-dev

vcpkg (cross-platform)

vcpkg install boost-asio boost-filesystem boost-regex boost-date-time boost-program-options
// vcpkg.json
{
  "dependencies": [
    "boost-asio",
    "boost-filesystem",
    "boost-regex",
    "boost-date-time",
    "boost-program-options"
  ]
}

From source

wget https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz
tar xzf boost_1_81_0.tar.gz
cd boost_1_81_0
./bootstrap.sh --prefix=/usr/local
./b2 install
LibraryHeader-onlyNeeds linking
Asio✅ (define BOOST_ASIO_HEADER_ONLY)boost_system (usually)
Filesystemboost_filesystem, boost_system
Regexboost_regex
DateTimeboost_date_time
Program_optionsboost_program_options

2. Boost.Asio

Timer example

#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
void print(const boost::system::error_code& ec) {
    if (!ec) {
        std::cout << "Timer expired!\n";
    }
}
int main() {
    asio::io_context io;
    asio::steady_timer timer(io, std::chrono::seconds(3));
    
    timer.async_wait(&print);
    
    std::cout << "Waiting...\n";
    io.run();  // Blocks until timer expires
    
    return 0;
}

TCP echo server (minimal)

#include <boost/asio.hpp>
#include <memory>
#include <iostream>
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
    tcp::socket socket_;
    std::array<char, 1024> buffer_;
public:
    explicit Session(tcp::socket socket) : socket_(std::move(socket)) {}
    
    void start() {
        do_read();
    }
    
private:
    void do_read() {
        auto self = shared_from_this();
        socket_.async_read_some(asio::buffer(buffer_),
            [this, self](boost::system::error_code ec, size_t length) {
                if (!ec) {
                    do_write(length);
                }
            });
    }
    
    void do_write(size_t length) {
        auto self = shared_from_this();
        asio::async_write(socket_, asio::buffer(buffer_, length),
            [this, self](boost::system::error_code ec, size_t) {
                if (!ec) {
                    do_read();
                }
            });
    }
};
class Server {
    tcp::acceptor acceptor_;
public:
    Server(asio::io_context& io, unsigned short port)
        : acceptor_(io, tcp::endpoint(tcp::v4(), port)) {
        do_accept();
    }
    
private:
    void do_accept() {
        acceptor_.async_accept([this](boost::system::error_code ec, tcp::socket socket) {
            if (!ec) {
                std::make_shared<Session>(std::move(socket))->start();
            }
            do_accept();
        });
    }
};
int main() {
    asio::io_context io;
    Server server(io, 8080);
    std::cout << "Echo server running on port 8080\n";
    io.run();
}

3. Boost.Filesystem

Path operations

#include <boost/filesystem.hpp>
#include <iostream>
namespace fs = boost::filesystem;
int main() {
    fs::path p = "/home/user/documents/file.txt";
    
    std::cout << "Parent: " << p.parent_path() << "\n";
    std::cout << "Filename: " << p.filename() << "\n";
    std::cout << "Extension: " << p.extension() << "\n";
    std::cout << "Stem: " << p.stem() << "\n";
    
    // Exists check
    if (fs::exists(p)) {
        std::cout << "File size: " << fs::file_size(p) << " bytes\n";
    }
    
    // Iterate directory
    for (const auto& entry : fs::directory_iterator(".")) {
        std::cout << entry.path() << "\n";
    }
    
    // Create directories
    fs::create_directories("path/to/nested/dir");
    
    // Copy file
    fs::copy_file("source.txt", "dest.txt", fs::copy_option::overwrite_if_exists);
    
    return 0;
}

Recursive directory traversal

void listFilesRecursive(const fs::path& dir) {
    for (const auto& entry : fs::recursive_directory_iterator(dir)) {
        if (fs::is_regular_file(entry)) {
            std::cout << entry.path() << " - " << fs::file_size(entry) << " bytes\n";
        }
    }
}

4. Boost.Regex

Basic matching

#include <boost/regex.hpp>
#include <iostream>
#include <string>
int main() {
    std::string text = "Email: [email protected], Phone: 123-456-7890";
    
    // Email regex
    boost::regex email_pattern(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)");
    boost::smatch match;
    
    if (boost::regex_search(text, match, email_pattern)) {
        std::cout << "Found email: " << match[0] << "\n";
    }
    
    // Replace
    boost::regex phone_pattern(R"(\d{3}-\d{3}-\d{4})");
    std::string result = boost::regex_replace(text, phone_pattern, "XXX-XXX-XXXX");
    std::cout << result << "\n";
    
    return 0;
}

Precompiled regex for performance

class LogParser {
    boost::regex pattern_;  // Precompile once
public:
    LogParser() : pattern_(R"((\d{4}-\d{2}-\d{2}) (\w+): (.+))") {}
    
    bool parse(const std::string& line, std::string& date, std::string& level, std::string& msg) {
        boost::smatch match;
        if (boost::regex_match(line, match, pattern_)) {
            date = match[1];
            level = match[2];
            msg = match[3];
            return true;
        }
        return false;
    }
};

5. Boost.DateTime

Date operations

#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>
namespace greg = boost::gregorian;
int main() {
    // Create dates
    greg::date today = greg::day_clock::local_day();
    greg::date birthday(2000, 1, 15);
    
    // Date arithmetic
    greg::date_duration age = today - birthday;
    std::cout << "Days old: " << age.days() << "\n";
    
    // Add days
    greg::date future = today + greg::days(30);
    std::cout << "30 days from now: " << future << "\n";
    
    // Day of week
    std::cout << "Today is: " << today.day_of_week() << "\n";
    
    // Date range
    greg::date_period period(today, greg::days(7));
    for (greg::day_iterator it(period.begin()); it <= period.end(); ++it) {
        std::cout << *it << "\n";
    }
    
    return 0;
}

Time operations

#include <boost/date_time/posix_time/posix_time.hpp>
namespace ptime = boost::posix_time;
int main() {
    ptime::ptime now = ptime::second_clock::local_time();
    std::cout << "Now: " << now << "\n";
    
    // Time duration
    ptime::time_duration td = ptime::hours(2) + ptime::minutes(30);
    ptime::ptime later = now + td;
    std::cout << "Later: " << later << "\n";
    
    // Parse from string
    ptime::ptime parsed = ptime::time_from_string("2024-01-15 14:30:00");
    
    return 0;
}

6. Boost.Program_options

Complete CLI parser

#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
int main(int argc, char* argv[]) {
    try {
        po::options_description desc("Allowed options");
        desc.add_options()
            ("help,h", "Show help message")
            ("input,i", po::value<std::string>()->required(), "Input file")
            ("output,o", po::value<std::string>()->default_value("output.txt"), "Output file")
            ("verbose,v", po::bool_switch()->default_value(false), "Verbose mode")
            ("threads,t", po::value<int>()->default_value(4), "Number of threads")
            ("config,c", po::value<std::string>(), "Config file")
        ;
        
        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        
        if (vm.count("help")) {
            std::cout << desc << "\n";
            return 0;
        }
        
        // Parse config file if provided
        if (vm.count("config")) {
            std::ifstream ifs(vm[config].as<std::string>());
            if (ifs) {
                po::store(po::parse_config_file(ifs, desc), vm);
            }
        }
        
        po::notify(vm);  // Throws if required options missing
        
        // Use options
        std::string input = vm[input].as<std::string>();
        std::string output = vm[output].as<std::string>();
        bool verbose = vm[verbose].as<bool>();
        int threads = vm[threads].as<int>();
        
        if (verbose) {
            std::cout << "Input: " << input << "\n";
            std::cout << "Output: " << output << "\n";
            std::cout << "Threads: " << threads << "\n";
        }
        
    } catch (const po::error& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }
    
    return 0;
}

Config file format

# config.ini
input = data.txt
output = result.txt
threads = 8
verbose = true

7. CMake integration

find_package

cmake_minimum_required(VERSION 3.14)
project(BoostExample)
set(CMAKE_CXX_STANDARD 17)
# Find Boost components
find_package(Boost 1.70 REQUIRED COMPONENTS 
    system
    filesystem
    regex
    date_time
    program_options
)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE
    Boost::system
    Boost::filesystem
    Boost::regex
    Boost::date_time
    Boost::program_options
)
# For Asio (header-only)
target_include_directories(myapp PRIVATE ${Boost_INCLUDE_DIRS})

With vcpkg toolchain

set(CMAKE_TOOLCHAIN_FILE "vcpkg/scripts/buildsystems/vcpkg.cmake")
find_package(Boost REQUIRED COMPONENTS filesystem regex)
target_link_libraries(myapp PRIVATE Boost::filesystem Boost::regex)

8. Real-world examples

Example 1: Log file analyzer

#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <fstream>
#include <map>
namespace fs = boost::filesystem;
namespace ptime = boost::posix_time;
class LogAnalyzer {
    boost::regex pattern_;
    std::map<std::string, int> error_counts_;
    
public:
    LogAnalyzer() : pattern_(R"((\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+): (.+))") {}
    
    void analyzeFile(const fs::path& path) {
        std::ifstream file(path.string());
        std::string line;
        
        while (std::getline(file, line)) {
            boost::smatch match;
            if (boost::regex_match(line, match, pattern_)) {
                std::string level = match[2];
                if (level == "ERROR" || level == "FATAL") {
                    error_counts_[level]++;
                }
            }
        }
    }
    
    void analyzeDirectory(const fs::path& dir) {
        for (const auto& entry : fs::recursive_directory_iterator(dir)) {
            if (fs::is_regular_file(entry) && entry.path().extension() == ".log") {
                std::cout << "Analyzing: " << entry.path() << "\n";
                analyzeFile(entry.path());
            }
        }
    }
    
    void printReport() {
        std::cout << "\n=== Error Report ===\n";
        for (const auto& [level, count] : error_counts_) {
            std::cout << level << ": " << count << "\n";
        }
    }
};
int main() {
    LogAnalyzer analyzer;
    analyzer.analyzeDirectory("/var/log/myapp");
    analyzer.printReport();
}

Example 2: Backup utility with CLI

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
namespace po = boost::program_options;
namespace fs = boost::filesystem;
namespace ptime = boost::posix_time;
class BackupTool {
public:
    void backup(const fs::path& source, const fs::path& dest, bool incremental) {
        if (!fs::exists(source)) {
            throw std::runtime_error("Source does not exist");
        }
        
        // Create timestamped backup directory
        ptime::ptime now = ptime::second_clock::local_time();
        std::string timestamp = ptime::to_iso_string(now);
        fs::path backup_dir = dest / timestamp;
        
        fs::create_directories(backup_dir);
        
        // Copy files
        for (const auto& entry : fs::recursive_directory_iterator(source)) {
            if (fs::is_regular_file(entry)) {
                fs::path relative = fs::relative(entry.path(), source);
                fs::path target = backup_dir / relative;
                
                fs::create_directories(target.parent_path());
                fs::copy_file(entry.path(), target);
                
                std::cout << "Backed up: " << relative << "\n";
            }
        }
        
        std::cout << "Backup completed: " << backup_dir << "\n";
    }
};
int main(int argc, char* argv[]) {
    try {
        po::options_description desc("Backup tool options");
        desc.add_options()
            ("help,h", "Show help")
            ("source,s", po::value<std::string>()->required(), "Source directory")
            ("dest,d", po::value<std::string>()->required(), "Destination directory")
            ("incremental,i", "Incremental backup")
        ;
        
        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        
        if (vm.count("help")) {
            std::cout << desc << "\n";
            return 0;
        }
        
        po::notify(vm);
        
        BackupTool tool;
        tool.backup(
            vm[source].as<std::string>(),
            vm[dest].as<std::string>(),
            vm.count("incremental") > 0
        );
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }
    
    return 0;
}

9. Performance comparison

Regex performance

#include <boost/regex.hpp>
#include <regex>
#include <chrono>
#include <iostream>
void benchmark() {
    std::string text = "[email protected], [email protected]";
    const int N = 10000;
    
    // Boost.Regex
    boost::regex boost_pattern(R"(\b[\w.%+-]+@[\w.-]+\.[A-Z|a-z]{2,}\b)");
    auto start1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) {
        boost::smatch match;
        boost::regex_search(text, match, boost_pattern);
    }
    auto end1 = std::chrono::high_resolution_clock::now();
    
    // std::regex
    std::regex std_pattern(R"(\b[\w.%+-]+@[\w.-]+\.[A-Z|a-z]{2,}\b)");
    auto start2 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < N; ++i) {
        std::smatch match;
        std::regex_search(text, match, std_pattern);
    }
    auto end2 = std::chrono::high_resolution_clock::now();
    
    auto boost_time = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1).count();
    auto std_time = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2).count();
    
    std::cout << "Boost.Regex: " << boost_time << "ms\n";
    std::cout << "std::regex: " << std_time << "ms\n";
}

Typical results:

  • Boost.Regex: Often faster and more consistent across compilers
  • std::regex: Performance varies by implementation (GCC vs Clang vs MSVC)

10. Common errors

Error 1: Undefined reference to boost

undefined reference to `boost::filesystem::path::codecvt()'

Fix: Link required libraries

target_link_libraries(myapp PRIVATE Boost::filesystem Boost::system)

Error 2: Version mismatch

error: 'boost::filesystem::copy_option' has not been declared

Fix: Check Boost version (API changed in 1.74)

// Boost 1.74+
fs::copy_file("a.txt", "b.txt", fs::copy_options::overwrite_existing);
// Older versions
fs::copy_file("a.txt", "b.txt", fs::copy_option::overwrite_if_exists);

Error 3: pthread on Linux

undefined reference to `pthread_create'

Fix: Add pthread

find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Boost::asio Threads::Threads)

Error 4: bad_any_cast in Program_options

terminate called after throwing an instance of 'boost::bad_any_cast'

Fix: Check if option exists before accessing

if (vm.count("threads")) {
    int threads = vm[threads].as<int>();
}

11. Best practices

1. Prefer std when available

// C++17+: Use std::filesystem
#include <filesystem>
namespace fs = std::filesystem;
// Pre-C++17: Use Boost
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

2. Precompile regex patterns

class Parser {
    boost::regex pattern_;  // Member, not local
public:
    Parser() : pattern_(R"(...)") {}  // Compile once
};

3. Handle Asio errors properly

void async_operation(boost::system::error_code ec) {
    if (ec) {
        if (ec == asio::error::eof) {
            // Connection closed
        } else if (ec == asio::error::connection_reset) {
            // Client disconnected
        } else {
            std::cerr << "Error: " << ec.message() << "\n";
        }
        return;
    }
    // Success path
}

12. Production patterns

Pattern 1: Asio with thread pool

asio::io_context io;
asio::thread_pool pool(4);
// Post work to pool
for (int i = 0; i < 100; ++i) {
    asio::post(pool, [i]() {
        // CPU-bound work
        process(i);
    });
}
pool.join();

Pattern 2: Graceful shutdown

asio::io_context io;
asio::signal_set signals(io, SIGINT, SIGTERM);
signals.async_wait([&](boost::system::error_code, int) {
    std::cout << "Shutting down...\n";
    io.stop();
});
io.run();

Pattern 3: Connection pooling

class ConnectionPool {
    asio::io_context& io_;
    std::vector<tcp::socket> pool_;
    std::mutex mutex_;
public:
    explicit ConnectionPool(asio::io_context& io, size_t size) : io_(io) {
        for (size_t i = 0; i < size; ++i) {
            pool_.emplace_back(io_);
        }
    }
    
    tcp::socket* acquire() {
        std::lock_guard<std::mutex> lock(mutex_);
        if (pool_.empty()) return nullptr;
        tcp::socket* sock = &pool_.back();
        pool_.pop_back();
        return sock;
    }
    
    void release(tcp::socket* sock) {
        std::lock_guard<std::mutex> lock(mutex_);
        pool_.push_back(std::move(*sock));
    }
};

Summary

  • Boost.Asio: Async I/O, networking, timers
  • Boost.Filesystem: Portable file operations (prefer std::filesystem in C++17+)
  • Boost.Regex: Pattern matching (often faster than std::regex)
  • Boost.DateTime: Calendar operations beyond chrono
  • Boost.Program_options: CLI argument parsing
  • CMake: find_package with COMPONENTS
  • Production: Thread pools, signal handling, connection pooling Next: nlohmann/json #27-2
    Previous: Compile-time reflection #26-3

Keywords

Boost, Asio, Filesystem, Regex, DateTime, Program_options, C++ libraries, async I/O


자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. Complete Boost guide: Install with apt or vcpkg, use Boost.Asio for async I/O, Filesystem for portable paths, Regex for … 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, Boost, Asio, Filesystem, Regex, DateTime, Program_options 등으로 검색하시면 이 글이 도움이 됩니다.