diff --git a/ctl/integral_constant.h b/ctl/integral_constant.h index df5a0a688..047b27354 100644 --- a/ctl/integral_constant.h +++ b/ctl/integral_constant.h @@ -11,10 +11,12 @@ struct integral_constant static constexpr T value = v; typedef T value_type; typedef integral_constant type; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; diff --git a/ctl/is_abstract.h b/ctl/is_abstract.h new file mode 100644 index 000000000..ccd26c123 --- /dev/null +++ b/ctl/is_abstract.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_ABSTRACT_H_ +#define CTL_IS_ABSTRACT_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_abstract : public integral_constant +{}; + +template +inline constexpr bool is_abstract_v = __is_abstract(T); + +} // namespace ctl + +#endif // CTL_IS_ABSTRACT_H_ diff --git a/ctl/is_base_of.h b/ctl/is_base_of.h new file mode 100644 index 000000000..a37456f26 --- /dev/null +++ b/ctl/is_base_of.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_BASE_OF_H_ +#define CTL_IS_BASE_OF_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_base_of : public integral_constant +{}; + +template +inline constexpr bool is_base_of_v = __is_base_of(Base, Derived); + +} // namespace ctl + +#endif // CTL_IS_BASE_OF_H_ diff --git a/ctl/is_class.h b/ctl/is_class.h new file mode 100644 index 000000000..3c958bd17 --- /dev/null +++ b/ctl/is_class.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_CLASS_H_ +#define CTL_IS_CLASS_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_class : public integral_constant +{}; + +template +inline constexpr bool is_class_v = __is_class(T); + +} // namespace ctl + +#endif // CTL_IS_CLASS_H_ diff --git a/ctl/is_constructible.h b/ctl/is_constructible.h new file mode 100644 index 000000000..4d202bdc5 --- /dev/null +++ b/ctl/is_constructible.h @@ -0,0 +1,19 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_CONSTRUCTIBLE_H_ +#define CTL_IS_CONSTRUCTIBLE_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_constructible + : public integral_constant +{}; + +template +inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); + +} // namespace ctl + +#endif // CTL_IS_CONSTRUCTIBLE_H_ diff --git a/ctl/is_empty.h b/ctl/is_empty.h new file mode 100644 index 000000000..a1cf31675 --- /dev/null +++ b/ctl/is_empty.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_EMPTY_H_ +#define CTL_IS_EMPTY_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_empty : public integral_constant +{}; + +template +inline constexpr bool is_empty_v = __is_empty(T); + +} // namespace ctl + +#endif // CTL_IS_EMPTY_H_ diff --git a/ctl/is_enum.h b/ctl/is_enum.h new file mode 100644 index 000000000..7d2cd5b78 --- /dev/null +++ b/ctl/is_enum.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_ENUM_H_ +#define CTL_IS_ENUM_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_enum : public integral_constant +{}; + +template +inline constexpr bool is_enum_v = __is_enum(T); + +} // namespace ctl + +#endif // CTL_IS_ENUM_H_ diff --git a/ctl/is_polymorphic.h b/ctl/is_polymorphic.h new file mode 100644 index 000000000..152b7af0b --- /dev/null +++ b/ctl/is_polymorphic.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_POLYMORPHIC_H_ +#define CTL_IS_POLYMORPHIC_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_polymorphic : public integral_constant +{}; + +template +inline constexpr bool is_polymorphic_v = __is_polymorphic(T); + +} // namespace ctl + +#endif // CTL_IS_POLYMORPHIC_H_ diff --git a/ctl/is_standard_layout.h b/ctl/is_standard_layout.h new file mode 100644 index 000000000..59ae380c8 --- /dev/null +++ b/ctl/is_standard_layout.h @@ -0,0 +1,19 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_STANDARD_LAYOUT_H_ +#define CTL_IS_STANDARD_LAYOUT_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_standard_layout + : public integral_constant +{}; + +template +inline constexpr bool is_standard_layout_v = __is_standard_layout(T); + +} // namespace ctl + +#endif // CTL_IS_STANDARD_LAYOUT_H_ diff --git a/ctl/is_trivial.h b/ctl/is_trivial.h new file mode 100644 index 000000000..c69c18f08 --- /dev/null +++ b/ctl/is_trivial.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_TRIVIAL_H_ +#define CTL_IS_TRIVIAL_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_trivial : public integral_constant +{}; + +template +inline constexpr bool is_trivial_v = __is_trivial(T); + +} // namespace ctl + +#endif // CTL_IS_TRIVIAL_H_ diff --git a/ctl/is_union.h b/ctl/is_union.h new file mode 100644 index 000000000..773c52e3b --- /dev/null +++ b/ctl/is_union.h @@ -0,0 +1,18 @@ +// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +#ifndef CTL_IS_UNION_H_ +#define CTL_IS_UNION_H_ +#include "integral_constant.h" + +namespace ctl { + +template +struct is_union : public integral_constant +{}; + +template +inline constexpr bool is_union_v = __is_union(T); + +} // namespace ctl + +#endif // CTL_IS_UNION_H_ diff --git a/test/ctl/is_base_of_test.cc b/test/ctl/is_base_of_test.cc new file mode 100644 index 000000000..8e64a75af --- /dev/null +++ b/test/ctl/is_base_of_test.cc @@ -0,0 +1,102 @@ +// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*- +// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi +// +// Copyright 2024 Justine Alexandra Roberts Tunney +// +// Permission to use, copy, modify, and/or distribute this software for +// any purpose with or without fee is hereby granted, provided that the +// above copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include "ctl/is_base_of.h" + +// #include +// #define ctl std + +// Test classes +class A +{}; +class B : public A +{}; +class C : public B +{}; +class D +{}; + +struct Empty +{}; + +template +class TemplateClass +{}; + +class VirtualBase +{}; +class VirtualDerived : virtual public VirtualBase +{}; + +int +main() +{ + // Test basic inheritance + if (!ctl::is_base_of_v) + return 1; + if (!ctl::is_base_of_v) + return 2; + if (ctl::is_base_of_v) + return 3; + if (ctl::is_base_of_v) + return 4; + if (ctl::is_base_of_v) + return 5; + + // Test with same type + if (!ctl::is_base_of_v) + return 6; + if (!ctl::is_base_of_v) + return 7; + + // Test with void + if (ctl::is_base_of_v) + return 8; + if (ctl::is_base_of_v) + return 9; + if (ctl::is_base_of_v) + return 10; + + // Test with fundamental types + if (ctl::is_base_of_v) + return 11; + if (ctl::is_base_of_v) + return 12; + if (ctl::is_base_of_v) + return 13; + + // Test with empty class + if (ctl::is_base_of_v) + return 14; + if (ctl::is_base_of_v) + return 15; + + // Test with template class + if (ctl::is_base_of_v, A>) + return 16; + if (ctl::is_base_of_v>) + return 17; + + // Test with virtual inheritance + if (!ctl::is_base_of_v) + return 18; + if (ctl::is_base_of_v) + return 19; + + return 0; // All tests passed +}