brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 47e81f3 Raw
220 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410 11// type_traits12 13// is_nothrow_invocable14 15#include <cstddef>16#include <type_traits>17#include <vector>18 19struct Tag {};20 21struct Implicit {22  Implicit(int) noexcept {}23};24 25struct ThrowsImplicit {26  ThrowsImplicit(int) {}27};28 29struct Explicit {30  explicit Explicit(int) noexcept {}31};32 33template <bool IsNoexcept, class Ret, class... Args>34struct CallObject {35  Ret operator()(Args&&...) const noexcept(IsNoexcept);36};37 38struct Sink {39  template <class... Args>40  void operator()(Args&&...) const noexcept {}41};42 43template <class Fn, class... Args>44constexpr bool throws_invocable() {45  return std::is_invocable<Fn, Args...>::value &&46         !std::is_nothrow_invocable<Fn, Args...>::value;47}48 49template <class Ret, class Fn, class... Args>50constexpr bool throws_invocable_r() {51  return std::is_invocable_r<Ret, Fn, Args...>::value &&52         !std::is_nothrow_invocable_r<Ret, Fn, Args...>::value;53}54 55void test_noexcept_function_pointers() {56  struct Dummy {57    void foo() noexcept {}58    static void bar() noexcept {}59  };60  // Check that PMF's and function pointers actually work and that61  // is_nothrow_invocable returns true for noexcept PMF's and function62  // pointers.63  static_assert(std::is_nothrow_invocable<decltype(&Dummy::foo), Dummy&>::value, "");64  static_assert(std::is_nothrow_invocable<decltype(&Dummy::bar)>::value, "");65}66 67int main(int, char**) {68  using AbominableFunc = void(...) const noexcept;69  //  Non-callable things70  {71    static_assert(!std::is_nothrow_invocable<void>::value, "");72    static_assert(!std::is_nothrow_invocable<const void>::value, "");73    static_assert(!std::is_nothrow_invocable<volatile void>::value, "");74    static_assert(!std::is_nothrow_invocable<const volatile void>::value, "");75    static_assert(!std::is_nothrow_invocable<std::nullptr_t>::value, "");76    static_assert(!std::is_nothrow_invocable<int>::value, "");77    static_assert(!std::is_nothrow_invocable<double>::value, "");78 79    static_assert(!std::is_nothrow_invocable<int[]>::value, "");80    static_assert(!std::is_nothrow_invocable<int[3]>::value, "");81 82    static_assert(!std::is_nothrow_invocable<int*>::value, "");83    static_assert(!std::is_nothrow_invocable<const int*>::value, "");84    static_assert(!std::is_nothrow_invocable<int const*>::value, "");85 86    static_assert(!std::is_nothrow_invocable<int&>::value, "");87    static_assert(!std::is_nothrow_invocable<const int&>::value, "");88    static_assert(!std::is_nothrow_invocable<int&&>::value, "");89 90    static_assert(!std::is_nothrow_invocable<int, std::vector<int> >::value,91                  "");92    static_assert(!std::is_nothrow_invocable<int, std::vector<int*> >::value,93                  "");94    static_assert(!std::is_nothrow_invocable<int, std::vector<int**> >::value,95                  "");96 97    static_assert(!std::is_nothrow_invocable<AbominableFunc>::value, "");98 99    //  with parameters100    static_assert(!std::is_nothrow_invocable<int, int>::value, "");101    static_assert(!std::is_nothrow_invocable<int, double, float>::value, "");102    static_assert(!std::is_nothrow_invocable<int, char, float, double>::value,103                  "");104    static_assert(!std::is_nothrow_invocable<Sink, AbominableFunc>::value, "");105    static_assert(!std::is_nothrow_invocable<Sink, void>::value, "");106    static_assert(!std::is_nothrow_invocable<Sink, const volatile void>::value,107                  "");108 109    static_assert(!std::is_nothrow_invocable_r<int, void>::value, "");110    static_assert(!std::is_nothrow_invocable_r<int, const void>::value, "");111    static_assert(!std::is_nothrow_invocable_r<int, volatile void>::value, "");112    static_assert(!std::is_nothrow_invocable_r<int, const volatile void>::value,113                  "");114    static_assert(!std::is_nothrow_invocable_r<int, std::nullptr_t>::value, "");115    static_assert(!std::is_nothrow_invocable_r<int, int>::value, "");116    static_assert(!std::is_nothrow_invocable_r<int, double>::value, "");117 118    static_assert(!std::is_nothrow_invocable_r<int, int[]>::value, "");119    static_assert(!std::is_nothrow_invocable_r<int, int[3]>::value, "");120 121    static_assert(!std::is_nothrow_invocable_r<int, int*>::value, "");122    static_assert(!std::is_nothrow_invocable_r<int, const int*>::value, "");123    static_assert(!std::is_nothrow_invocable_r<int, int const*>::value, "");124 125    static_assert(!std::is_nothrow_invocable_r<int, int&>::value, "");126    static_assert(!std::is_nothrow_invocable_r<int, const int&>::value, "");127    static_assert(!std::is_nothrow_invocable_r<int, int&&>::value, "");128 129    static_assert(!std::is_nothrow_invocable_r<int, std::vector<int> >::value,130                  "");131    static_assert(!std::is_nothrow_invocable_r<int, std::vector<int*> >::value,132                  "");133    static_assert(!std::is_nothrow_invocable_r<int, std::vector<int**> >::value,134                  "");135    static_assert(!std::is_nothrow_invocable_r<void, AbominableFunc>::value,136                  "");137 138    //  with parameters139    static_assert(!std::is_nothrow_invocable_r<int, int, int>::value, "");140    static_assert(!std::is_nothrow_invocable_r<int, int, double, float>::value,141                  "");142    static_assert(143        !std::is_nothrow_invocable_r<int, int, char, float, double>::value, "");144    static_assert(145        !std::is_nothrow_invocable_r<void, Sink, AbominableFunc>::value, "");146    static_assert(!std::is_nothrow_invocable_r<void, Sink, void>::value, "");147    static_assert(148        !std::is_nothrow_invocable_r<void, Sink, const volatile void>::value,149        "");150  }151 152  {153    // Check that the conversion to the return type is properly checked154    using Fn = CallObject<true, int>;155    static_assert(std::is_nothrow_invocable_r<Implicit, Fn>::value, "");156    static_assert(std::is_nothrow_invocable_r<double, Fn>::value, "");157    static_assert(std::is_nothrow_invocable_r<const volatile void, Fn>::value,158                  "");159    static_assert(throws_invocable_r<ThrowsImplicit, Fn>(), "");160    static_assert(!std::is_nothrow_invocable<Fn(), Explicit>(), "");161  }162  {163    // Check that the conversion to the parameters is properly checked164    using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>;165    static_assert(166        std::is_nothrow_invocable<Fn, Implicit&, ThrowsImplicit&>::value, "");167    static_assert(std::is_nothrow_invocable<Fn, int, ThrowsImplicit&>::value,168                  "");169    static_assert(throws_invocable<Fn, int, int>(), "");170    static_assert(!std::is_nothrow_invocable<Fn>::value, "");171  }172  {173    // Check that the noexcept-ness of function objects is checked.174    using Fn = CallObject<true, void>;175    using Fn2 = CallObject<false, void>;176    static_assert(std::is_nothrow_invocable<Fn>::value, "");177    static_assert(throws_invocable<Fn2>(), "");178  }179  {180    // Check that PMD derefs are noexcept181    using Fn = int(Tag::*);182    static_assert(std::is_nothrow_invocable<Fn, Tag&>::value, "");183    static_assert(std::is_nothrow_invocable_r<Implicit, Fn, Tag&>::value, "");184    static_assert(throws_invocable_r<ThrowsImplicit, Fn, Tag&>(), "");185  }186  {187    // Check that it's fine if the result type is non-moveable.188    struct CantMove {189      CantMove() = default;190      CantMove(CantMove&&) = delete;191    };192 193    static_assert(!std::is_move_constructible_v<CantMove>);194    static_assert(!std::is_copy_constructible_v<CantMove>);195 196    using Fn = CantMove() noexcept;197 198    static_assert(std::is_nothrow_invocable_r<CantMove, Fn>::value);199    static_assert(!std::is_nothrow_invocable_r<CantMove, Fn, int>::value);200 201    static_assert(std::is_nothrow_invocable_r_v<CantMove, Fn>);202    static_assert(!std::is_nothrow_invocable_r_v<CantMove, Fn, int>);203  }204  {205    // Check for is_nothrow_invocable_v206    using Fn = CallObject<true, int>;207    static_assert(std::is_nothrow_invocable_v<Fn>, "");208    static_assert(!std::is_nothrow_invocable_v<Fn, int>, "");209  }210  {211    // Check for is_nothrow_invocable_r_v212    using Fn = CallObject<true, int>;213    static_assert(std::is_nothrow_invocable_r_v<void, Fn>, "");214    static_assert(!std::is_nothrow_invocable_r_v<int, Fn, int>, "");215  }216  test_noexcept_function_pointers();217 218  return 0;219}220