测试_第11章_C++17特性.cpp

← 测试总览 · 目录

编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第11章_C++17特性.cpp -o t && ./t(需先 cd 测试/

// 第11章测试:C++17 新特性
#include <print>
#include <optional>
#include <variant>
#include <any>
#include <string>
#include <string_view>
#include <map>
#include <vector>
#include <fstream>
#include <filesystem>
#include <numeric>
#include <type_traits>

namespace fs = std::filesystem;

int failures = 0;
#define CHECK(expr)                                                         \
    do {                                                                    \
        if (!(expr)) {                                                      \
            ++failures;                                                     \
            std::println("FAIL 第{}行: {}", __LINE__, #expr);              \
        }                                                                   \
    } while (0)

std::optional<int> find_max(const std::vector<int>& v) {
    if (v.empty()) return std::nullopt;
    return *std::max_element(v.begin(), v.end());
}

[[nodiscard]] int must_use() { return 1; }

int main() {
    // 11.1 结构化绑定
    std::map<std::string, int> m{{"a", 1}, {"b", 2}};
    int sum = 0;
    for (auto [k, val] : m) sum += val;
    CHECK(sum == 3);
    auto [x, y] = std::pair{3, 4};
    CHECK(x == 3 && y == 4);
    auto [ta, tb, tc] = std::tuple{1, 2.5, std::string{"s"}};
    CHECK(ta == 1 && tb == 2.5 && tc == "s");

    // 11.2 if 初始化
    auto it = m.find("b");
    (void)it;
    if (auto it2 = m.find("b"); it2 != m.end()) {
        CHECK(it2->second == 2);
    }
    // it2 在这里已不可见(能编译通过即证明作用域正确)

    // 11.3 optional
    CHECK(find_max({3, 1, 4}) == 4);
    CHECK(!find_max({}).has_value());
    CHECK(find_max({}).value_or(-1) == -1);

    // 11.4 variant
    std::variant<int, double, std::string> v;
    v = 42;
    CHECK(std::get_if<int>(&v) != nullptr);
    v = "text";
    CHECK(std::get_if<std::string>(&v) != nullptr);
    CHECK(std::get<std::string>(v) == "text");
    // 错误类型访问会抛 bad_variant_access
    bool threw = false;
    try { std::get<int>(v); } catch (const std::bad_variant_access&) { threw = true; }
    CHECK(threw);
    // visit 统一访问(注意:lambda 要为每种类型都能编译,
    // 这里用 if constexpr 区分类型——见第十章)
    int visited = 0;
    std::visit([&visited](const auto& val) {
        if constexpr (std::is_same_v<std::decay_t<decltype(val)>, std::string>)
            visited = (int)val.size();
    }, v);
    CHECK(visited == 4);

    // 11.5 any
    std::any a = 42;
    a = std::string("hello");
    CHECK(std::any_cast<std::string>(a) == "hello");

    // 11.7 filesystem
    fs::path test_dir = "/tmp/fs_test";
    fs::remove_all(test_dir);                           // 清干净
    fs::create_directories(test_dir / "sub" / "deep");
    CHECK(fs::exists(test_dir));
    CHECK(fs::is_directory(test_dir));

    fs::path f = test_dir / "data.txt";
    {
        std::ofstream out(f);
        out << "hello";
    }
    CHECK(fs::exists(f));
    CHECK(fs::is_regular_file(f));
    CHECK(fs::file_size(f) == 5);
    CHECK(f.stem() == "data");
    CHECK(f.extension() == ".txt");

    // 目录遍历
    int files = 0, dirs = 0;
    for (const auto& entry : fs::recursive_directory_iterator(test_dir)) {
        if (entry.is_regular_file()) ++files;
        if (entry.is_directory()) ++dirs;
    }
    CHECK(files == 1);
    CHECK(dirs == 2);                                   // sub 和 sub/deep

    fs::remove_all(test_dir);
    CHECK(!fs::exists(test_dir));

    // 11.11 nodiscard 属性(编译期验证:用法正确)
    CHECK(must_use() == 1);

    // 11.12 clamp / size
    CHECK(std::clamp(10, 0, 5) == 5);
    CHECK(std::clamp(-3, 0, 5) == 0);
    int raw[4] = {1, 2, 3, 4};
    CHECK(std::size(raw) == 4);

    if (failures == 0) std::println("全部通过");
    return failures;
}