Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -4711,12 +4711,18 @@ #ifdef _LIBCPP_UNDERLYING_TYPE -template -struct underlying_type +template ::value> +struct __impl_underlying_type { typedef _LIBCPP_UNDERLYING_TYPE(_Tp) type; }; +template +struct __impl_underlying_type<_Tp, false> { }; + +template +struct underlying_type : __impl_underlying_type<_Tp> { }; + #if _LIBCPP_STD_VER > 11 template using underlying_type_t = typename underlying_type<_Tp>::type; #endif Index: test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.fail.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// type_traits + +// underlying_type + +#include + +int main(int, char**) +{ + // no `type` member indicates that `int` is not an enum + using t = std::underlying_type::type; // expected-error {{no type named 'type' in 'std::__1::underlying_type'}} + return 0; +} Index: test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp =================================================================== --- test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp +++ test/std/utilities/meta/meta.trans/meta.trans.other/underlying_type.pass.cpp @@ -27,6 +27,18 @@ enum F { W = UINT_MAX }; #endif // TEST_UNSIGNED_UNDERLYING_TYPE +template ::type> +std::true_type test_sfinae(int); + +template +std::false_type test_sfinae(...); + +template +constexpr bool test_sfinae_v() // This is a function so it is valid pre-c++14 +{ + return decltype(test_sfinae(0))::value; +} + int main(int, char**) { static_assert((std::is_same::type, int>::value), @@ -52,6 +64,9 @@ static_assert((std::is_same, char>::value), ""); #endif // TEST_STD_VER > 11 #endif // TEST_STD_VER >= 11 + + static_assert(!test_sfinae_v(), "Not an enum"); + static_assert(test_sfinae_v(), "Is an enum"); return 0; }