Author: marshall Date: Sat Nov 26 09:49:40 2016 New Revision: 287981 URL: http://llvm.org/viewvc/llvm-project?rev=287981&view=rev Log: Implement the 'detection idiom' from LFTS v2
Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_or.pass.cpp libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp Modified: libcxx/trunk/include/experimental/type_traits Modified: libcxx/trunk/include/experimental/type_traits URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/type_traits?rev=287981&r1=287980&r2=287981&view=diff ============================================================================== --- libcxx/trunk/include/experimental/type_traits (original) +++ libcxx/trunk/include/experimental/type_traits Sat Nov 26 09:49:40 2016 @@ -172,6 +172,45 @@ inline namespace fundamentals_v1 { template <class T> using raw_invocation_type_t = typename raw_invocation_type<T>::type; + // 3.3.3, Logical operator traits + template<class... B> struct conjunction; + template<class... B> constexpr bool conjunction_v = conjunction<B...>::value; + template<class... B> struct disjunction; + template<class... B> constexpr bool disjunction_v = disjunction<B...>::value; + template<class B> struct negation; + template<class B> constexpr bool negation_v = negation<B>::value; + + // 3.3.4, Detection idiom + template <class...> using void_t = void; + + struct nonesuch { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; + }; + + template <template<class...> class Op, class... Args> + using is_detected = see below; + template <template<class...> class Op, class... Args> + constexpr bool is_detected_v = is_detected<Op, Args...>::value; + template <template<class...> class Op, class... Args> + using detected_t = see below; + template <class Default, template<class...> class Op, class... Args> + using detected_or = see below; + template <class Default, template<class...> class Op, class... Args> + using detected_or_t = typename detected_or<Default, Op, Args...>::type; + template <class Expected, template<class...> class Op, class... Args> + using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>; + template <class Expected, template<class...> class Op, class... Args> + constexpr bool is_detected_exact_v + = is_detected_exact<Expected, Op, Args...>::value; + template <class To, template<class...> class Op, class... Args> + using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>; + template <class To, template<class...> class Op, class... Args> + constexpr bool is_detected_convertible_v + = is_detected_convertible<To, Op, Args...>::value; + } // namespace fundamentals_v1 } // namespace experimental } // namespace std @@ -420,6 +459,52 @@ template <class _Tp> using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type; */ +// 3.3.4, Detection idiom +template <class...> using void_t = void; + +struct nonesuch { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch (nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; + }; + +template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args> +struct _DETECTOR { + using value_t = false_type; + using type = _Default; + }; + +template <class _Default, template <class...> class _Op, class... _Args> +struct _DETECTOR<_Default, void_t<_Op<_Args...>>, _Op, _Args...> { + using value_t = true_type; + using type = _Op<_Args...>; + }; + + +template <template<class...> class _Op, class... _Args> + using is_detected = typename _DETECTOR<nonesuch, void, _Op, _Args...>::value_t; +template <template<class...> class _Op, class... _Args> + using detected_t = typename _DETECTOR<nonesuch, void, _Op, _Args...>::type; +template <template<class...> class _Op, class... _Args> + _LIBCPP_CONSTEXPR bool is_detected_v = is_detected<_Op, _Args...>::value; + +template <class Default, template<class...> class _Op, class... _Args> + using detected_or = _DETECTOR<Default, void, _Op, _Args...>; +template <class Default, template<class...> class _Op, class... _Args> + using detected_or_t = typename detected_or<Default, _Op, _Args...>::type; + +template <class Expected, template<class...> class _Op, class... _Args> + using is_detected_exact = is_same<Expected, detected_t<_Op, _Args...>>; +template <class Expected, template<class...> class _Op, class... _Args> + _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, _Op, _Args...>::value; + +template <class To, template<class...> class _Op, class... _Args> + using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, To>; +template <class To, template<class...> class _Op, class... _Args> + _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, _Op, _Args...>::value; + + _LIBCPP_END_NAMESPACE_LFTS #endif /* _LIBCPP_STD_VER > 11 */ Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_or.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_or.pass.cpp?rev=287981&view=auto ============================================================================== --- libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_or.pass.cpp (added) +++ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_or.pass.cpp Sat Nov 26 09:49:40 2016 @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// <experimental/type_traits> + +#include <experimental/type_traits> +#include <string> + +#include "test_macros.h" + +namespace ex = std::experimental; + +template <typename T> + using hasFoo = typename T::Foo; + +struct yesFoo { + using Foo = int; +}; + +struct noFoo { +}; + + +template <typename T, typename Res> +void test() { + static_assert( std::is_same<Res, typename ex::detected_or <double, hasFoo, T>::type>::value, "" ); + static_assert( std::is_same<Res, typename ex::detected_or_t<double, hasFoo, T> >::value, "" ); +} + +int main () { + test<yesFoo, int>(); + test<noFoo, double>(); +} Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp?rev=287981&view=auto ============================================================================== --- libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp (added) +++ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp Sat Nov 26 09:49:40 2016 @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// <experimental/type_traits> + +#include <experimental/type_traits> +#include <string> + +#include "test_macros.h" + +namespace ex = std::experimental; + +template <typename T> + using callFoo = decltype(std::declval<T&>().Foo()); + +struct yesFoo { + int Foo() { return 0; } +}; + +struct noFoo { +}; + +struct wrongFoo { + std::string Foo() { return ""; } +}; + +struct convertibleFoo { + long Foo() { return 0; } +}; + + +template <typename T, typename Res> +void test() { + static_assert( std::is_same<Res, typename ex::detected_t<callFoo, T>>::value, "" ); +} + +int main () { + test<yesFoo, int>(); + test<noFoo, ex::nonesuch>(); // lookup failure returns nonesuch + test<wrongFoo, std::string>(); +} Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp?rev=287981&view=auto ============================================================================== --- libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp (added) +++ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp Sat Nov 26 09:49:40 2016 @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// <experimental/type_traits> + +#include <experimental/type_traits> +#include <string> + +#include "test_macros.h" + +namespace ex = std::experimental; + +template <typename T> + using copy_assign_t = decltype(std::declval<T&>() = std::declval<T const &>()); + +struct not_assignable { + not_assignable & operator=(const not_assignable&) = delete; +}; + +template <typename T, bool b> +void test() { + static_assert( b == ex::is_detected <copy_assign_t, T>::value, "" ); + static_assert( b == ex::is_detected_v<copy_assign_t, T>, "" ); +} + +int main () { + test<int, true>(); + test<std::string, true>(); + test<not_assignable, false>(); +} Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp?rev=287981&view=auto ============================================================================== --- libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp (added) +++ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp Sat Nov 26 09:49:40 2016 @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// <experimental/type_traits> + +#include <experimental/type_traits> +#include <string> + +#include "test_macros.h" + +namespace ex = std::experimental; + +template <typename T> + using callFoo = decltype(std::declval<T&>().Foo()); + +struct yesFoo { + int Foo() { return 0; } +}; + +struct noFoo { +}; + +struct wrongFoo { + std::string Foo() { return ""; } +}; + +struct convertibleFoo { + long Foo() { return 0; } +}; + + +template <typename T, bool b> +void test() { + static_assert( b == ex::is_detected_convertible <int, callFoo, T>::value, "" ); + static_assert( b == ex::is_detected_convertible_v<int, callFoo, T>, "" ); +} + +int main () { + test<yesFoo, true>(); + test<noFoo, false>(); + test<wrongFoo, false>(); + test<convertibleFoo, true>(); +} Added: libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp?rev=287981&view=auto ============================================================================== --- libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp (added) +++ libcxx/trunk/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp Sat Nov 26 09:49:40 2016 @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// <experimental/type_traits> + +#include <experimental/type_traits> +#include <string> + +#include "test_macros.h" + +namespace ex = std::experimental; + +template <typename T> + using callFoo = decltype(std::declval<T&>().Foo()); + +struct yesFoo { + int Foo() { return 0; } +}; + +struct noFoo { +}; + +struct wrongFoo { + std::string Foo() { return ""; } +}; + +struct convertibleFoo { + long Foo() { return 0; } +}; + +template <typename T, bool b> +void test() { + static_assert( b == ex::is_detected_exact <int, callFoo, T>::value, "" ); + static_assert( b == ex::is_detected_exact_v<int, callFoo, T>, "" ); +} + +int main () { + test<yesFoo, true>(); + test<noFoo, false>(); + test<wrongFoo, false>(); + test<convertibleFoo, false>(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits