| /* |
| * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #include "precompiled.hpp" |
| #include "memory/allStatic.hpp" |
| #include "metaprogramming/enableIf.hpp" |
| #include "utilities/debug.hpp" |
| #include "unittest.hpp" |
| |
| #include <type_traits> |
| |
| class EnableIfTest: AllStatic { |
| class A: AllStatic { |
| public: |
| template <bool condition> |
| static typename EnableIf<condition, char>::type test(); |
| template <bool condition> |
| static typename EnableIf<!condition, long>::type test(); |
| }; |
| |
| static const bool A_test_true_is_char = sizeof(A::test<true>()) == sizeof(char); |
| STATIC_ASSERT(A_test_true_is_char); |
| |
| static const bool A_test_false_is_long = sizeof(A::test<false>()) == sizeof(long); |
| STATIC_ASSERT(A_test_false_is_long); |
| }; |
| |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| static T sub1(T x) { return x - 1; } |
| |
| TEST(TestEnableIf, one_decl_and_def) { |
| EXPECT_EQ(15, sub1(16)); |
| } |
| |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| static T sub2(T x); |
| |
| template<typename T, ENABLE_IF_SDEFN(std::is_integral<T>::value)> |
| T sub2(T x) { return x - 2; } |
| |
| TEST(TestEnableIf, separate_decl_and_def) { |
| EXPECT_EQ(14, sub2(16)); |
| } |
| |
| template<typename T> |
| struct TestEnableIfNested { |
| template<typename U, ENABLE_IF(std::is_integral<U>::value)> |
| static U sub1(U x); |
| }; |
| |
| template<typename T> |
| template<typename U, ENABLE_IF_SDEFN(std::is_integral<U>::value)> |
| U TestEnableIfNested<T>::sub1(U x) { return x - 1; } |
| |
| TEST(TestEnableIf, nested_separate_decl_and_def) { |
| EXPECT_EQ(15, TestEnableIfNested<void>::sub1(16)); |
| } |
| |
| // Demonstrate workaround for non-dependent condition. |
| template<typename T> |
| struct TestEnableIfNonDependent { |
| // Dependent is used to make the ENABLE_IF condition dependent on |
| // the type parameters for this function. |
| template<typename Dependent = T, ENABLE_IF(std::is_same<int, Dependent>::value)> |
| static T value() { return T{}; } |
| static int instantiate() { return 5; } |
| }; |
| |
| TEST(TestEnableIf, non_dependent) { |
| EXPECT_EQ(int{}, TestEnableIfNonDependent<int>::value()); |
| // This fails to compile if the ENABLE_IF for value() directly uses |
| // T rather than indirectly via Dependent. |
| EXPECT_EQ(5, TestEnableIfNonDependent<void>::instantiate()); |
| } |