diff options
Diffstat (limited to 'test/std/utilities/meta/meta.rel')
4 files changed, 287 insertions, 275 deletions
diff --git a/test/std/utilities/meta/meta.rel/is_callable.pass.cpp b/test/std/utilities/meta/meta.rel/is_callable.pass.cpp deleted file mode 100644 index 4c85f440b..000000000 --- a/test/std/utilities/meta/meta.rel/is_callable.pass.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// type_traits - -// is_callable - -// Most testing of is_callable is done within the [meta.trans.other] result_of -// tests. - -#include <type_traits> -#include <functional> -#include <memory> - -#include "test_macros.h" - -struct Tag {}; -struct DerFromTag : Tag {}; - -struct Implicit { - Implicit(int) {} -}; - -struct Explicit { - explicit Explicit(int) {} -}; - -struct NotCallableWithInt { - int operator()(int) = delete; - int operator()(Tag) { return 42; } -}; - -int main() -{ - { - using Fn = int(Tag::*)(int); - using RFn = int(Tag::*)(int) &&; - // INVOKE bullet 1, 2 and 3 - { - // Bullet 1 - static_assert(std::is_callable<Fn(Tag&, int)>::value, ""); - static_assert(std::is_callable<Fn(DerFromTag&, int)>::value, ""); - static_assert(std::is_callable<RFn(Tag&&, int)>::value, ""); - static_assert(!std::is_callable<RFn(Tag&, int)>::value, ""); - static_assert(!std::is_callable<Fn(Tag&)>::value, ""); - static_assert(!std::is_callable<Fn(Tag const&, int)>::value, ""); - } - { - // Bullet 2 - using T = std::reference_wrapper<Tag>; - using DT = std::reference_wrapper<DerFromTag>; - using CT = std::reference_wrapper<const Tag>; - static_assert(std::is_callable<Fn(T&, int)>::value, ""); - static_assert(std::is_callable<Fn(DT&, int)>::value, ""); - static_assert(std::is_callable<Fn(const T&, int)>::value, ""); - static_assert(std::is_callable<Fn(T&&, int)>::value, ""); - static_assert(!std::is_callable<Fn(CT&, int)>::value, ""); - static_assert(!std::is_callable<RFn(T, int)>::value, ""); - } - { - // Bullet 3 - using T = Tag*; - using DT = DerFromTag*; - using CT = const Tag*; - using ST = std::unique_ptr<Tag>; - static_assert(std::is_callable<Fn(T&, int)>::value, ""); - static_assert(std::is_callable<Fn(DT&, int)>::value, ""); - static_assert(std::is_callable<Fn(const T&, int)>::value, ""); - static_assert(std::is_callable<Fn(T&&, int)>::value, ""); - static_assert(std::is_callable<Fn(ST, int)>::value, ""); - static_assert(!std::is_callable<Fn(CT&, int)>::value, ""); - static_assert(!std::is_callable<RFn(T, int)>::value, ""); - } - } - { - // Bullets 4, 5 and 6 - using Fn = int (Tag::*); - static_assert(!std::is_callable<Fn()>::value, ""); - { - // Bullet 4 - static_assert(std::is_callable<Fn(Tag&)>::value, ""); - static_assert(std::is_callable<Fn(DerFromTag&)>::value, ""); - static_assert(std::is_callable<Fn(Tag&&)>::value, ""); - static_assert(std::is_callable<Fn(Tag const&)>::value, ""); - } - { - // Bullet 5 - using T = std::reference_wrapper<Tag>; - using DT = std::reference_wrapper<DerFromTag>; - using CT = std::reference_wrapper<const Tag>; - static_assert(std::is_callable<Fn(T&)>::value, ""); - static_assert(std::is_callable<Fn(DT&)>::value, ""); - static_assert(std::is_callable<Fn(const T&)>::value, ""); - static_assert(std::is_callable<Fn(T&&)>::value, ""); - static_assert(std::is_callable<Fn(CT&)>::value, ""); - } - { - // Bullet 6 - using T = Tag*; - using DT = DerFromTag*; - using CT = const Tag*; - using ST = std::unique_ptr<Tag>; - static_assert(std::is_callable<Fn(T&)>::value, ""); - static_assert(std::is_callable<Fn(DT&)>::value, ""); - static_assert(std::is_callable<Fn(const T&)>::value, ""); - static_assert(std::is_callable<Fn(T&&)>::value, ""); - static_assert(std::is_callable<Fn(ST)>::value, ""); - static_assert(std::is_callable<Fn(CT&)>::value, ""); - } - } - { - // INVOKE bullet 7 - { - // Function pointer - using Fp = void(*)(Tag&, int); - static_assert(std::is_callable<Fp(Tag&, int)>::value, ""); - static_assert(std::is_callable<Fp(DerFromTag&, int)>::value, ""); - static_assert(!std::is_callable<Fp(const Tag&, int)>::value, ""); - static_assert(!std::is_callable<Fp()>::value, ""); - static_assert(!std::is_callable<Fp(Tag&)>::value, ""); - } - { - // Function reference - using Fp = void(&)(Tag&, int); - static_assert(std::is_callable<Fp(Tag&, int)>::value, ""); - static_assert(std::is_callable<Fp(DerFromTag&, int)>::value, ""); - static_assert(!std::is_callable<Fp(const Tag&, int)>::value, ""); - static_assert(!std::is_callable<Fp()>::value, ""); - static_assert(!std::is_callable<Fp(Tag&)>::value, ""); - } - { - // Function object - using Fn = NotCallableWithInt; - static_assert(std::is_callable<Fn(Tag)>::value, ""); - static_assert(!std::is_callable<Fn(int)>::value, ""); - } - } - { - // Check that the conversion to the return type is properly checked - using Fn = int(*)(); - static_assert(std::is_callable<Fn(), Implicit>::value, ""); - static_assert(std::is_callable<Fn(), double>::value, ""); - static_assert(std::is_callable<Fn(), const volatile void>::value, ""); - static_assert(!std::is_callable<Fn(), Explicit>::value, ""); - } - { - // Check for is_callable_v - using Fn = void(*)(); - static_assert(std::is_callable_v<Fn()>, ""); - static_assert(!std::is_callable_v<Fn(int)>, ""); - } -} diff --git a/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp b/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp new file mode 100644 index 000000000..1b2a9286f --- /dev/null +++ b/test/std/utilities/meta/meta.rel/is_invocable.pass.cpp @@ -0,0 +1,166 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_invocable + +// Most testing of is_invocable is done within the [meta.trans.other] result_of +// tests. + +#include <type_traits> +#include <functional> +#include <memory> + +#include "test_macros.h" + +struct Tag {}; +struct DerFromTag : Tag {}; + +struct Implicit { + Implicit(int) {} +}; + +struct Explicit { + explicit Explicit(int) {} +}; + +struct NotCallableWithInt { + int operator()(int) = delete; + int operator()(Tag) { return 42; } +}; + +int main() +{ + { + using Fn = int(Tag::*)(int); + using RFn = int(Tag::*)(int) &&; + // INVOKE bullet 1, 2 and 3 + { + // Bullet 1 + static_assert(std::is_invocable<Fn, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fn, DerFromTag&, int>::value, ""); + static_assert(std::is_invocable<RFn, Tag&&, int>::value, ""); + static_assert(!std::is_invocable<RFn, Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fn, Tag&>::value, ""); + static_assert(!std::is_invocable<Fn, Tag const&, int>::value, ""); + } + { + // Bullet 2 + using T = std::reference_wrapper<Tag>; + using DT = std::reference_wrapper<DerFromTag>; + using CT = std::reference_wrapper<const Tag>; + static_assert(std::is_invocable<Fn, T&, int>::value, ""); + static_assert(std::is_invocable<Fn, DT&, int>::value, ""); + static_assert(std::is_invocable<Fn, const T&, int>::value, ""); + static_assert(std::is_invocable<Fn, T&&, int>::value, ""); + static_assert(!std::is_invocable<Fn, CT&, int>::value, ""); + static_assert(!std::is_invocable<RFn, T, int>::value, ""); + } + { + // Bullet 3 + using T = Tag*; + using DT = DerFromTag*; + using CT = const Tag*; + using ST = std::unique_ptr<Tag>; + static_assert(std::is_invocable<Fn, T&, int>::value, ""); + static_assert(std::is_invocable<Fn, DT&, int>::value, ""); + static_assert(std::is_invocable<Fn, const T&, int>::value, ""); + static_assert(std::is_invocable<Fn, T&&, int>::value, ""); + static_assert(std::is_invocable<Fn, ST, int>::value, ""); + static_assert(!std::is_invocable<Fn, CT&, int>::value, ""); + static_assert(!std::is_invocable<RFn, T, int>::value, ""); + } + } + { + // Bullets 4, 5 and 6 + using Fn = int (Tag::*); + static_assert(!std::is_invocable<Fn>::value, ""); + { + // Bullet 4 + static_assert(std::is_invocable<Fn, Tag&>::value, ""); + static_assert(std::is_invocable<Fn, DerFromTag&>::value, ""); + static_assert(std::is_invocable<Fn, Tag&&>::value, ""); + static_assert(std::is_invocable<Fn, Tag const&>::value, ""); + } + { + // Bullet 5 + using T = std::reference_wrapper<Tag>; + using DT = std::reference_wrapper<DerFromTag>; + using CT = std::reference_wrapper<const Tag>; + static_assert(std::is_invocable<Fn, T&>::value, ""); + static_assert(std::is_invocable<Fn, DT&>::value, ""); + static_assert(std::is_invocable<Fn, const T&>::value, ""); + static_assert(std::is_invocable<Fn, T&&>::value, ""); + static_assert(std::is_invocable<Fn, CT&>::value, ""); + } + { + // Bullet 6 + using T = Tag*; + using DT = DerFromTag*; + using CT = const Tag*; + using ST = std::unique_ptr<Tag>; + static_assert(std::is_invocable<Fn, T&>::value, ""); + static_assert(std::is_invocable<Fn, DT&>::value, ""); + static_assert(std::is_invocable<Fn, const T&>::value, ""); + static_assert(std::is_invocable<Fn, T&&>::value, ""); + static_assert(std::is_invocable<Fn, ST>::value, ""); + static_assert(std::is_invocable<Fn, CT&>::value, ""); + } + } + { + // INVOKE bullet 7 + { + // Function pointer + using Fp = void(*)(Tag&, int); + static_assert(std::is_invocable<Fp, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, ""); + static_assert(!std::is_invocable<Fp, const Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fp>::value, ""); + static_assert(!std::is_invocable<Fp, Tag&>::value, ""); + } + { + // Function reference + using Fp = void(&)(Tag&, int); + static_assert(std::is_invocable<Fp, Tag&, int>::value, ""); + static_assert(std::is_invocable<Fp, DerFromTag&, int>::value, ""); + static_assert(!std::is_invocable<Fp, const Tag&, int>::value, ""); + static_assert(!std::is_invocable<Fp>::value, ""); + static_assert(!std::is_invocable<Fp, Tag&>::value, ""); + } + { + // Function object + using Fn = NotCallableWithInt; + static_assert(std::is_invocable<Fn, Tag>::value, ""); + static_assert(!std::is_invocable<Fn, int>::value, ""); + } + } + { + // Check that the conversion to the return type is properly checked + using Fn = int(*)(); + static_assert(std::is_invocable_r<Implicit, Fn>::value, ""); + static_assert(std::is_invocable_r<double, Fn>::value, ""); + static_assert(std::is_invocable_r<const volatile void, Fn>::value, ""); + static_assert(!std::is_invocable_r<Explicit, Fn>::value, ""); + } + { + // Check for is_invocable_v + using Fn = void(*)(); + static_assert(std::is_invocable_v<Fn>, ""); + static_assert(!std::is_invocable_v<Fn, int>, ""); + } + { + // Check for is_invocable_r_v + using Fn = void(*)(); + static_assert(std::is_invocable_r_v<void, Fn>, ""); + static_assert(!std::is_invocable_r_v<int, Fn>, ""); + } +} diff --git a/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp b/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp deleted file mode 100644 index eefa6d1f2..000000000 --- a/test/std/utilities/meta/meta.rel/is_nothrow_callable.pass.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// type_traits - -// is_nothrow_callable - -#include <type_traits> -#include <functional> - -#include "test_macros.h" - -struct Tag {}; - -struct Implicit { - Implicit(int) noexcept {} -}; - -struct ThrowsImplicit { - ThrowsImplicit(int) {} -}; - -struct Explicit { - explicit Explicit(int) noexcept {} -}; - -template <bool IsNoexcept, class Ret, class ...Args> -struct CallObject { - Ret operator()(Args&&...) const noexcept(IsNoexcept); -}; - -template <class Fn> -constexpr bool throws_callable() { - return std::is_callable<Fn>::value && - !std::is_nothrow_callable<Fn>::value; -} - -template <class Fn, class Ret> -constexpr bool throws_callable() { - return std::is_callable<Fn, Ret>::value && - !std::is_nothrow_callable<Fn, Ret>::value; -} - -// FIXME(EricWF) Don't test the where noexcept is *not* part of the type system -// once implementations have caught up. -void test_noexcept_function_pointers() -{ - struct Dummy { void foo() noexcept {} static void bar() noexcept {} }; -#if !defined(__cpp_noexcept_function_type) - { - // Check that PMF's and function pointers *work*. is_nothrow_callable will always - // return false because 'noexcept' is not part of the function type. - static_assert(throws_callable<decltype(&Dummy::foo)(Dummy&)>(), ""); - static_assert(throws_callable<decltype(&Dummy::bar)()>(), ""); - } -#else - { - // Check that PMF's and function pointers actually work and that - // is_nothrow_callable returns true for noexcept PMF's and function - // pointers. - static_assert(std::is_nothrow_callable<decltype(&Dummy::foo)(Dummy&)>::value, ""); - static_assert(std::is_nothrow_callable<decltype(&Dummy::bar)()>::value, ""); - } -#endif -} - -int main() -{ - { - // Check that the conversion to the return type is properly checked - using Fn = CallObject<true, int>; - static_assert(std::is_nothrow_callable<Fn(), Implicit>::value, ""); - static_assert(std::is_nothrow_callable<Fn(), double>::value, ""); - static_assert(std::is_nothrow_callable<Fn(), const volatile void>::value, ""); - static_assert(throws_callable<Fn(), ThrowsImplicit>(), ""); - static_assert(!std::is_nothrow_callable<Fn(), Explicit>(), ""); - } - { - // Check that the conversion to the parameters is properly checked - using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>; - static_assert(std::is_nothrow_callable<Fn(Implicit&, ThrowsImplicit&)>::value, ""); - static_assert(std::is_nothrow_callable<Fn(int, ThrowsImplicit&)>::value, ""); - static_assert(throws_callable<Fn(int, int)>(), ""); - static_assert(!std::is_nothrow_callable<Fn()>::value, ""); - } - { - // Check that the noexcept-ness of function objects is checked. - using Fn = CallObject<true, void>; - using Fn2 = CallObject<false, void>; - static_assert(std::is_nothrow_callable<Fn()>::value, ""); - static_assert(throws_callable<Fn2()>(), ""); - } - { - // Check that PMD derefs are noexcept - using Fn = int (Tag::*); - static_assert(std::is_nothrow_callable<Fn(Tag&)>::value, ""); - static_assert(std::is_nothrow_callable<Fn(Tag&), Implicit>::value, ""); - static_assert(throws_callable<Fn(Tag&), ThrowsImplicit>(), ""); - } - { - // Check for is_nothrow_callable_v - using Fn = CallObject<true, int>; - static_assert(std::is_nothrow_callable_v<Fn()>, ""); - static_assert(!std::is_nothrow_callable_v<Fn(int)>, ""); - } - test_noexcept_function_pointers(); -} diff --git a/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp b/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp new file mode 100644 index 000000000..3be3d46f2 --- /dev/null +++ b/test/std/utilities/meta/meta.rel/is_nothrow_invocable.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// type_traits + +// is_nothrow_invocable + +#include <type_traits> +#include <functional> + +#include "test_macros.h" + +struct Tag {}; + +struct Implicit { + Implicit(int) noexcept {} +}; + +struct ThrowsImplicit { + ThrowsImplicit(int) {} +}; + +struct Explicit { + explicit Explicit(int) noexcept {} +}; + +template <bool IsNoexcept, class Ret, class ...Args> +struct CallObject { + Ret operator()(Args&&...) const noexcept(IsNoexcept); +}; + +template <class Fn, class ...Args> +constexpr bool throws_invocable() { + return std::is_invocable<Fn, Args...>::value && + !std::is_nothrow_invocable<Fn, Args...>::value; +} + +template <class Ret, class Fn, class ...Args> +constexpr bool throws_invocable_r() { + return std::is_invocable_r<Ret, Fn, Args...>::value && + !std::is_nothrow_invocable_r<Ret, Fn, Args...>::value; +} + +// FIXME(EricWF) Don't test the where noexcept is *not* part of the type system +// once implementations have caught up. +void test_noexcept_function_pointers() +{ + struct Dummy { void foo() noexcept {} static void bar() noexcept {} }; +#if !defined(__cpp_noexcept_function_type) + { + // Check that PMF's and function pointers *work*. is_nothrow_invocable will always + // return false because 'noexcept' is not part of the function type. + static_assert(throws_invocable<decltype(&Dummy::foo), Dummy&>(), ""); + static_assert(throws_invocable<decltype(&Dummy::bar)>(), ""); + } +#else + { + // Check that PMF's and function pointers actually work and that + // is_nothrow_invocable returns true for noexcept PMF's and function + // pointers. + static_assert(std::is_nothrow_invocable<decltype(&Dummy::foo), Dummy&>::value, ""); + static_assert(std::is_nothrow_invocable<decltype(&Dummy::bar)>::value, ""); + } +#endif +} + +int main() +{ + { + // Check that the conversion to the return type is properly checked + using Fn = CallObject<true, int>; + static_assert(std::is_nothrow_invocable_r<Implicit, Fn>::value, ""); + static_assert(std::is_nothrow_invocable_r<double, Fn>::value, ""); + static_assert(std::is_nothrow_invocable_r<const volatile void, Fn>::value, ""); + static_assert(throws_invocable_r<ThrowsImplicit, Fn>(), ""); + static_assert(!std::is_nothrow_invocable<Fn(), Explicit>(), ""); + } + { + // Check that the conversion to the parameters is properly checked + using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>; + static_assert(std::is_nothrow_invocable<Fn, Implicit&, ThrowsImplicit&>::value, ""); + static_assert(std::is_nothrow_invocable<Fn, int, ThrowsImplicit&>::value, ""); + static_assert(throws_invocable<Fn, int, int>(), ""); + static_assert(!std::is_nothrow_invocable<Fn>::value, ""); + } + { + // Check that the noexcept-ness of function objects is checked. + using Fn = CallObject<true, void>; + using Fn2 = CallObject<false, void>; + static_assert(std::is_nothrow_invocable<Fn>::value, ""); + static_assert(throws_invocable<Fn2>(), ""); + } + { + // Check that PMD derefs are noexcept + using Fn = int (Tag::*); + static_assert(std::is_nothrow_invocable<Fn, Tag&>::value, ""); + static_assert(std::is_nothrow_invocable_r<Implicit, Fn, Tag&>::value, ""); + static_assert(throws_invocable_r<ThrowsImplicit, Fn, Tag&>(), ""); + } + { + // Check for is_nothrow_invocable_v + using Fn = CallObject<true, int>; + static_assert(std::is_nothrow_invocable_v<Fn>, ""); + static_assert(!std::is_nothrow_invocable_v<Fn, int>, ""); + } + { + // Check for is_nothrow_invocable_r_v + using Fn = CallObject<true, int>; + static_assert(std::is_nothrow_invocable_r_v<void, Fn>, ""); + static_assert(!std::is_nothrow_invocable_r_v<int, Fn, int>, ""); + } + test_noexcept_function_pointers(); +} |