CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
247 lines
8.4 KiB
C++
247 lines
8.4 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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++26
|
|
|
|
// constant_wrapper
|
|
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator+(T) noexcept -> constant_wrapper<(+T::value)>
|
|
// { return {}; }
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator-(T) noexcept -> constant_wrapper<(-T::value)>
|
|
// { return {}; }
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator~(T) noexcept -> constant_wrapper<(~T::value)>
|
|
// { return {}; }
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator!(T) noexcept -> constant_wrapper<(!T::value)>
|
|
// { return {}; }
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator&(T) noexcept -> constant_wrapper<(&T::value)>
|
|
// { return {}; }
|
|
// template<constexpr-param T>
|
|
// friend constexpr auto operator*(T) noexcept -> constant_wrapper<(*T::value)>
|
|
// { return {}; }
|
|
|
|
#include <cassert>
|
|
#include <concepts>
|
|
#include <utility>
|
|
|
|
#include "helpers.h"
|
|
|
|
struct WithOps {
|
|
int value;
|
|
|
|
constexpr WithOps(int v) : value(v) {}
|
|
|
|
friend constexpr auto operator+(WithOps w) { return WithOps{+w.value}; }
|
|
friend constexpr auto operator-(WithOps w) { return WithOps{-w.value}; }
|
|
friend constexpr auto operator~(WithOps w) { return WithOps{~w.value}; }
|
|
friend constexpr auto operator!(WithOps w) { return WithOps{!w.value}; }
|
|
friend constexpr auto operator&(WithOps w) { return WithOps{w.value + 42}; }
|
|
friend constexpr auto operator*(WithOps w) { return WithOps{w.value - 42}; }
|
|
};
|
|
|
|
struct OpsReturnNonStructural {
|
|
int value;
|
|
|
|
constexpr OpsReturnNonStructural(int v) : value(v) {}
|
|
|
|
friend constexpr auto operator+(OpsReturnNonStructural o) { return NonStructural{+o.value}; }
|
|
friend constexpr auto operator-(OpsReturnNonStructural o) { return NonStructural{-o.value}; }
|
|
friend constexpr auto operator~(OpsReturnNonStructural o) { return NonStructural{~o.value}; }
|
|
friend constexpr auto operator!(OpsReturnNonStructural o) { return NonStructural{!o.value}; }
|
|
friend constexpr auto operator&(OpsReturnNonStructural o) { return NonStructural{o.value + 42}; }
|
|
friend constexpr auto operator*(OpsReturnNonStructural o) { return NonStructural{o.value - 42}; }
|
|
};
|
|
|
|
struct NoOps {};
|
|
|
|
template <class T>
|
|
concept HasPlus = requires(T t) {
|
|
{ +t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasMinus = requires(T t) {
|
|
{ -t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasBitNot = requires(T t) {
|
|
{ ~t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNot = requires(T t) {
|
|
{ !t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasBitAnd = requires(T t) {
|
|
{ &t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasDeref = requires(T t) {
|
|
{ *t };
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptPlus = requires(T t) {
|
|
{ +t } noexcept;
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptMinus = requires(T t) {
|
|
{ -t } noexcept;
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptBitNot = requires(T t) {
|
|
{ ~t } noexcept;
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptNot = requires(T t) {
|
|
{ !t } noexcept;
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptBitAnd = requires(T t) {
|
|
{ &t } noexcept;
|
|
};
|
|
|
|
template <class T>
|
|
concept HasNoexceptDeref = requires(T t) {
|
|
{ *t } noexcept;
|
|
};
|
|
|
|
static_assert(HasPlus<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasMinus<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasBitNot<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNot<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasBitAnd<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasDeref<std::constant_wrapper<WithOps{42}>>);
|
|
|
|
static_assert(HasNoexceptPlus<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNoexceptMinus<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNoexceptBitNot<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNoexceptNot<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNoexceptBitAnd<std::constant_wrapper<WithOps{42}>>);
|
|
static_assert(HasNoexceptDeref<std::constant_wrapper<WithOps{42}>>);
|
|
|
|
static_assert(HasNoexceptPlus<std::constant_wrapper<42>>);
|
|
static_assert(HasNoexceptMinus<std::constant_wrapper<42>>);
|
|
static_assert(HasNoexceptBitNot<std::constant_wrapper<42>>);
|
|
static_assert(HasNoexceptNot<std::constant_wrapper<42>>);
|
|
static_assert(HasNoexceptBitAnd<std::constant_wrapper<42>>);
|
|
static_assert(!HasDeref<std::constant_wrapper<42>>);
|
|
|
|
static_assert(!HasPlus<std::constant_wrapper<NoOps{}>>);
|
|
static_assert(!HasMinus<std::constant_wrapper<NoOps{}>>);
|
|
static_assert(!HasBitNot<std::constant_wrapper<NoOps{}>>);
|
|
static_assert(!HasNot<std::constant_wrapper<NoOps{}>>);
|
|
static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);
|
|
static_assert(!HasDeref<std::constant_wrapper<NoOps{}>>);
|
|
|
|
// The operators from constant_wrapper do not exist, but they can be implicited converted
|
|
// to the underlying type and use its operators instead.
|
|
static_assert(HasPlus<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(HasMinus<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(HasBitNot<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(HasNot<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(HasBitAnd<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(HasDeref<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
|
|
static_assert(!HasNoexceptPlus<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(!HasNoexceptMinus<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(!HasNoexceptBitNot<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(!HasNoexceptNot<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(!HasNoexceptBitAnd<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
static_assert(!HasNoexceptDeref<std::constant_wrapper<OpsReturnNonStructural{42}>>);
|
|
|
|
constexpr bool test() {
|
|
{
|
|
// int
|
|
std::constant_wrapper<42> cw42;
|
|
|
|
std::same_as<std::constant_wrapper<42>> decltype(auto) result = +cw42;
|
|
static_assert(result == 42);
|
|
|
|
std::same_as<std::constant_wrapper<-42>> decltype(auto) result2 = -cw42;
|
|
static_assert(result2 == -42);
|
|
|
|
std::same_as<std::constant_wrapper<~42>> decltype(auto) result3 = ~cw42;
|
|
static_assert(result3 == ~42);
|
|
|
|
std::same_as<std::constant_wrapper<!42>> decltype(auto) result4 = !cw42;
|
|
static_assert(result4 == !42);
|
|
|
|
std::same_as<std::constant_wrapper<&cw42.value>> decltype(auto) result5 = &cw42;
|
|
static_assert(result5 == &cw42.value);
|
|
}
|
|
|
|
{
|
|
// WithOps
|
|
std::constant_wrapper<WithOps{42}> cwWithOps;
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{42}>> decltype(auto) result = +cwWithOps;
|
|
static_assert(result.value.value == 42);
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{-42}>> decltype(auto) result2 = -cwWithOps;
|
|
static_assert(result2.value.value == -42);
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{~42}>> decltype(auto) result3 = ~cwWithOps;
|
|
static_assert(result3.value.value == ~42);
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{!42}>> decltype(auto) result4 = !cwWithOps;
|
|
static_assert(result4.value.value == !42);
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{84}>> decltype(auto) result5 = &cwWithOps;
|
|
static_assert(result5.value.value == 84);
|
|
|
|
std::same_as<std::constant_wrapper<WithOps{0}>> decltype(auto) result6 = *cwWithOps;
|
|
static_assert(result6.value.value == 0);
|
|
}
|
|
|
|
{
|
|
// Return non-structural type
|
|
// Will use underlying type's runtime operators
|
|
std::constant_wrapper<OpsReturnNonStructural{42}> cwOpsReturnNonStructural;
|
|
|
|
std::same_as<NonStructural> decltype(auto) result = +cwOpsReturnNonStructural;
|
|
assert(result.get() == 42);
|
|
|
|
std::same_as<NonStructural> decltype(auto) result2 = -cwOpsReturnNonStructural;
|
|
assert(result2.get() == -42);
|
|
|
|
std::same_as<NonStructural> decltype(auto) result3 = ~cwOpsReturnNonStructural;
|
|
assert(result3.get() == ~42);
|
|
|
|
std::same_as<NonStructural> decltype(auto) result4 = !cwOpsReturnNonStructural;
|
|
assert(result4.get() == !42);
|
|
|
|
std::same_as<NonStructural> decltype(auto) result5 = &cwOpsReturnNonStructural;
|
|
assert(result5.get() == 84);
|
|
|
|
std::same_as<NonStructural> decltype(auto) result6 = *cwOpsReturnNonStructural;
|
|
assert(result6.get() == 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int main(int, char**) {
|
|
test();
|
|
static_assert(test());
|
|
|
|
return 0;
|
|
}
|