blob: 4af29d20943ea77e78c3f245fdf7ee727b293f4c [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++20
// <chrono>
//
// template<class T> struct is_clock;
// template<class T> constexpr bool is_clock_v = is_clock<T>::value;
#include <chrono>
#include <ratio>
#include "test_macros.h"
struct EmptyStruct {};
// Test structs missing required members
struct MissingRep {
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<MissingRep>;
static constexpr bool is_steady = false;
static time_point now();
};
struct MissingPeriod {
using rep = long;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<MissingPeriod>;
static constexpr bool is_steady = false;
static time_point now();
};
struct MissingDuration {
using rep = long;
using time_point = long;
static constexpr bool is_steady = false;
static time_point now();
};
struct MissingTimePoint {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
static constexpr bool is_steady = false;
static std::chrono::time_point<MissingTimePoint> now();
};
struct MissingIsSteady {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<MissingIsSteady>;
static time_point now();
};
struct MissingNow {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<MissingNow>;
static constexpr bool is_steady = false;
};
// Valid clock types
struct ValidSteadyClock {
using rep = long long;
using period = std::nano;
using duration = std::chrono::nanoseconds;
using time_point = std::chrono::time_point<ValidSteadyClock>;
static constexpr bool is_steady = true;
static time_point now();
};
struct ValidSystemClock {
using rep = long long;
using period = std::micro;
using duration = std::chrono::microseconds;
using time_point = std::chrono::time_point<ValidSystemClock>;
static constexpr bool is_steady = false;
static time_point now();
};
// Test clocks with invalid is_steady type
struct WrongIsSteadyType {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<WrongIsSteadyType>;
static bool is_steady; // Not const bool
static time_point now();
};
struct WrongIsSteadyNonBool {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<WrongIsSteadyNonBool>;
static constexpr int is_steady = 1; // Not bool
static time_point now();
};
// Test clocks with invalid now() return type
struct WrongNowReturnType {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<WrongNowReturnType>;
static constexpr bool is_steady = false;
static int now(); // Wrong return type
};
// Test clocks with invalid period type
struct WrongPeriodType {
using rep = long;
using period = int; // Not a ratio
using duration = std::chrono::seconds;
using time_point = std::chrono::time_point<WrongPeriodType>;
static constexpr bool is_steady = false;
static time_point now();
};
// Test clocks with wrong duration type
struct WrongDurationType {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::milliseconds; // Should be duration<long, ratio<1>>
using time_point = std::chrono::time_point<WrongDurationType>;
static constexpr bool is_steady = false;
static time_point now();
};
// Test clocks with wrong time_point type
struct WrongTimePointType {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::duration<long, std::ratio<1>>;
using time_point = int; // Not a time_point
static constexpr bool is_steady = false;
static time_point now();
};
struct WrongTimePointClock {
using rep = long;
using period = std::ratio<1>;
using duration = std::chrono::duration<long, std::ratio<1>>;
using time_point = std::chrono::time_point<ValidSystemClock>; // Wrong clock type
static constexpr bool is_steady = false;
static time_point now();
};
// Valid clock with time_point that has matching duration instead of matching clock
struct ValidClockWithDurationMatch {
using rep = int;
using period = std::milli;
using duration = std::chrono::duration<int, std::milli>;
using time_point = std::chrono::time_point<ValidSystemClock, duration>; // Valid: matches duration
static constexpr bool is_steady = false;
static time_point now();
};
// Test both is_clock and is_clock_v
static_assert(std::chrono::is_clock<std::chrono::system_clock>::value);
static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);
// Test standard clock types
static_assert(std::chrono::is_clock_v<std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<std::chrono::high_resolution_clock>);
// Test non-clock types
static_assert(!std::chrono::is_clock_v<EmptyStruct>);
static_assert(!std::chrono::is_clock_v<int>);
static_assert(!std::chrono::is_clock_v<void>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock::time_point>);
static_assert(!std::chrono::is_clock_v<std::chrono::seconds>);
static_assert(!std::chrono::is_clock_v<std::chrono::milliseconds>);
// Test structs missing required members
static_assert(!std::chrono::is_clock_v<MissingRep>);
static_assert(!std::chrono::is_clock_v<MissingPeriod>);
static_assert(!std::chrono::is_clock_v<MissingDuration>);
static_assert(!std::chrono::is_clock_v<MissingTimePoint>);
static_assert(!std::chrono::is_clock_v<MissingIsSteady>);
static_assert(!std::chrono::is_clock_v<MissingNow>);
// Test valid custom clocks
static_assert(std::chrono::is_clock_v<ValidSteadyClock>);
static_assert(std::chrono::is_clock_v<ValidSystemClock>);
static_assert(std::chrono::is_clock_v<ValidClockWithDurationMatch>);
// cv-qualified and reference types
static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<volatile std::chrono::system_clock>);
static_assert(std::chrono::is_clock_v<const volatile std::chrono::system_clock>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock&&>);
static_assert(!std::chrono::is_clock_v<const std::chrono::system_clock&>);
// array and pointer types
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[]>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock[10]>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock*>);
static_assert(!std::chrono::is_clock_v<std::chrono::system_clock* const>);
// The Standard defined a minimum set of checks and allowed implementation to perform stricter checks. The following
// static asserts are implementation specific and a conforming standard library implementation doesn't have to produce
// the same outcome.
// Test clocks with invalid is_steady type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyType>); // is_steady not const bool
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type
// Test clocks with invalid now() return type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point
// Test clocks with invalid period type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio
// Test clocks with wrong duration type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period>
// Test clocks with wrong time_point type
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointType>); // time_point is not a time_point
LIBCPP_STATIC_ASSERT(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration