Rewrite std::get<Type>(...) helper using constexpr functions.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@274418 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-07-02 03:18:30 +00:00
parent 5fb1e0ab01
commit 22c3e76205
6 changed files with 62 additions and 119 deletions

View File

@@ -986,39 +986,39 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT
}
#if _LIBCPP_STD_VER > 11
// get by type
template <typename _T1, size_t _Idx, typename... _Args>
struct __find_exactly_one_t_helper;
// -- find exactly one
template <typename _T1, size_t _Idx, typename... _Args>
struct __find_exactly_one_t_checker {
static constexpr size_t value = _Idx;
// Check the rest of the list to make sure there's only one
static_assert ( __find_exactly_one_t_helper<_T1, 0, _Args...>::value == -1, "type can only occur once in type list" );
};
namespace __find_detail {
static constexpr size_t __not_found = -1;
static constexpr size_t __ambiguous = __not_found - 1;
template <typename _T1, size_t _Idx>
struct __find_exactly_one_t_helper <_T1, _Idx> {
static constexpr size_t value = -1;
};
inline _LIBCPP_INLINE_VISIBILITY
constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) {
return !__matches ? __res :
(__res == __not_found ? __curr_i : __ambiguous);
}
template <typename _T1, size_t _Idx, typename _Head, typename... _Args>
struct __find_exactly_one_t_helper <_T1, _Idx, _Head, _Args...> {
static constexpr size_t value =
std::conditional<
std::is_same<_T1, _Head>::value,
__find_exactly_one_t_checker<_T1, _Idx, _Args...>,
__find_exactly_one_t_helper <_T1, _Idx+1, _Args...>
>::type::value;
};
template <size_t _Nx>
inline _LIBCPP_INLINE_VISIBILITY
constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) {
return __i == _Nx ? __not_found :
__find_idx_return(__i, __find_idx(__i + 1, __matches), __matches[__i]);
}
template <class _T1, class ..._Args>
struct __find_exactly_one_checked {
static constexpr bool __matches[] = {is_same<_T1, _Args>::value...};
static constexpr size_t value = __find_detail::__find_idx(0, __matches);
static_assert (value != __not_found, "type not found in type list" );
static_assert(value != __ambiguous,"type occurs more than once in type list");
};
} // namespace __find_detail;
template <typename _T1, typename... _Args>
struct __find_exactly_one_t {
static constexpr size_t value = __find_exactly_one_t_helper<_T1, 0, _Args...>::value;
static_assert ( value != -1, "type not found in type list" );
};
struct __find_exactly_one_t
: public __find_detail::__find_exactly_one_checked<_T1, _Args...> {
};
template <class _T1, class... _Args>
inline _LIBCPP_INLINE_VISIBILITY

View File

@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// 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
#include <tuple>
#include <string>
struct UserType {};
void test_bad_index() {
std::tuple<long, long, char, std::string, char, UserType, char> t1;
(void)std::get<int>(t1); // expected-error@tuple:* {{type not found}}
(void)std::get<long>(t1); // expected-note {{requested here}}
(void)std::get<char>(t1); // expected-note {{requested here}}
// expected-error@tuple:* 2 {{type occurs more than once}}
}
void test_bad_return_type() {
typedef std::unique_ptr<int> upint;
std::tuple<upint> t;
upint p = std::get<upint>(t); // expected-error{{deleted copy constructor}}
}
int main()
{
test_bad_index();
test_bad_return_type();
}

View File

@@ -1,23 +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
#include <tuple>
#include <string>
#include <complex>
#include <cassert>
int main()
{
typedef std::complex<float> cf;
auto t1 = std::make_tuple<int, std::string> ( 42, "Hi" );
assert (( std::get<cf>(t1) == cf {1,2} )); // no such type
}

View File

@@ -1,23 +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
#include <tuple>
#include <string>
#include <complex>
#include <cassert>
int main()
{
typedef std::complex<float> cf;
auto t1 = std::make_tuple<int, int, std::string, cf> ( 42, 21, "Hi", { 1,2 } );
assert ( std::get<int>(t1) == 42 ); // two ints here
}

View File

@@ -1,23 +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
#include <tuple>
#include <string>
#include <complex>
#include <cassert>
int main()
{
typedef std::complex<float> cf;
auto t1 = std::make_tuple<double, int, std::string, cf, int> ( 42, 21, "Hi", { 1,2 } );
assert ( std::get<int>(t1) == 42 ); // two ints here (one at the end)
}

View File

@@ -1,23 +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
#include <tuple>
#include <string>
#include <memory>
#include <cassert>
int main()
{
typedef std::unique_ptr<int> upint;
std::tuple<upint> t(upint(new int(4)));
upint p = std::get<upint>(t);
}