Commit d23c4452 authored by Allison Vacanti's avatar Allison Vacanti
Browse files

Merge branch 'upstream-taotuple' into tmp

* upstream-taotuple:
  taotuple 2018-05-15 (e3de8c97)
parents b00f6c1c b3b14de7
The MIT License (MIT)
Copyright (c) 2015 Daniel Frey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# The Art of C++ / Tuple
[![Release](https://img.shields.io/github/release/taocpp/tuple.svg)](https://github.com/taocpp/tuple/releases/latest)
[![License](https://img.shields.io/github/license/taocpp/tuple.svg)](#license)
[![TravisCI](https://travis-ci.org/taocpp/tuple.svg)](https://travis-ci.org/taocpp/tuple)
[![Issues](https://img.shields.io/github/issues/taocpp/tuple.svg)](https://github.com/taocpp/tuple/issues)
The Art of C++ / Tuple is a C++11 header-only reference implementation of
[`std::tuple`](http://en.cppreference.com/w/cpp/utility/tuple).
## Rationale
Why another implementation of `std::tuple`? To provide a proof-of-concept that,
when avoiding recursion, code can benefit in significant ways. I prepared a talk
about it, including some benchmarks.
[Download presentation](https://github.com/taocpp/tuple/blob/master/Variadic%20Templates.pdf)
TL;DR: GCC 5 on Linux with libstdc++'s `std::tuple` requires 19.6s and an instantiation
depth of at least 3.719 to compile an
[example](https://github.com/taocpp/tuple/blob/master/src/test/tuple/tuple_benchmark.cpp)
generating a tuple with 265 elements via `std::tuple_cat`.
`tao::tuple` requires 1.2s and an instantiation depth of 26 on the same system.
Apple LLVM 7.0 (~Clang 3.7) with libc++'s `std::tuple` requires 70s and an instantiation
depth of 514 to compile the example. `tao::tuple` requires 1.7s and an instantiation depth
of 15 on the same system.
## Compatibility
* Requires C++11 or newer.
* Tested with GCC 4.8+ and Clang 3.4+.
## License
The Art of C++ is certified [Open Source](http://www.opensource.org/docs/definition.html) software. It may be used for any purpose, including commercial purposes, at absolutely no cost. It is distributed under the terms of the [MIT license](http://www.opensource.org/licenses/mit-license.html) reproduced here.
> Copyright (c) 2015 Daniel Frey
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef SimpleTuple_h
#define SimpleTuple_h
// A simple tuple implementation for simple compilers.
//
// Most platforms use the taocpp/tuple implementation in thirdparty/taotuple,
// but not all are capable of handling the metaprogramming techniques used.
// This simple recursion-based tuple implementation is used where tao fails.
#include <type_traits>
#include <utility>
#ifndef TAOCPP_ANNOTATION
#ifdef __CUDACC__
#define TAOCPP_ANNOTATION __host__ __device__
#else
#define TAOCPP_ANNOTATION
#endif // __CUDACC__
#endif // TAOCPP_ANNOTATION
namespace simple_tuple
{
namespace detail
{
template <std::size_t Index, typename Head>
class tuple_leaf
{
protected:
Head Value;
public:
TAOCPP_ANNOTATION constexpr tuple_leaf()
: Value()
{
}
TAOCPP_ANNOTATION constexpr tuple_leaf(const Head& value)
: Value(value)
{
}
TAOCPP_ANNOTATION constexpr tuple_leaf(const tuple_leaf& o)
: Value(o.Value)
{
}
TAOCPP_ANNOTATION constexpr tuple_leaf(tuple_leaf&& o)
: Value(std::move(o.Value))
{
}
template <typename Other>
TAOCPP_ANNOTATION constexpr tuple_leaf(Other&& o)
: Value(std::forward<Other>(o))
{
}
static TAOCPP_ANNOTATION constexpr Head& Get(tuple_leaf& o) noexcept { return o.Value; }
static TAOCPP_ANNOTATION constexpr const Head& Get(const tuple_leaf& o) noexcept
{
return o.Value;
}
TAOCPP_ANNOTATION
tuple_leaf& operator=(tuple_leaf& o)
{
this->Value = o.Value;
return *this;
}
};
template <std::size_t Index, typename... Ts>
class tuple_impl;
template <std::size_t Idx, typename HeadT, typename... TailTs>
class tuple_impl<Idx, HeadT, TailTs...> : public tuple_impl<Idx + 1, TailTs...>,
private tuple_leaf<Idx, HeadT>
{
public:
template <std::size_t, typename...>
friend class tuple_impl;
using Tail = tuple_impl<Idx + 1, TailTs...>;
using Leaf = tuple_leaf<Idx, HeadT>;
using Head = HeadT;
static const std::size_t Index = Idx;
TAOCPP_ANNOTATION constexpr tuple_impl()
: Tail()
, Leaf()
{
}
explicit TAOCPP_ANNOTATION constexpr tuple_impl(const HeadT& h, const TailTs&... ts)
: Tail(ts...)
, Leaf(h)
{
}
// The enable_if is needed to ensure that tail lengths match (otherwise empty
// constructors would be called).
template <typename OHeadT,
typename... OTailTs,
typename = typename std::enable_if<sizeof...(TailTs) == sizeof...(OTailTs)>::type>
explicit TAOCPP_ANNOTATION constexpr tuple_impl(OHeadT&& h, OTailTs&&... ts)
: Tail(std::forward<OTailTs>(ts)...)
, Leaf(std::forward<OHeadT>(h))
{
}
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl&) = default;
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl&& o)
: Tail(std::move(GetTail(o)))
, Leaf(std::forward<Head>(GetHead(o)))
{
}
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl<Idx, Ts...>& o)
: Tail(tuple_impl<Idx, Ts...>::GetTail(o))
, Leaf(tuple_impl<Idx, Ts...>::GetHead(o))
{
}
template <typename OHead, typename... OTailTs>
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl<Idx, OHead, OTailTs...>&& o)
: Tail(std::move(tuple_impl<Idx, OHead, OTailTs...>::GetTail(o)))
, Leaf(std::forward<OHead>(tuple_impl<Idx, OHead, OTailTs...>::GetHead(o)))
{
}
TAOCPP_ANNOTATION
tuple_impl& operator=(const tuple_impl& o)
{
GetHead(*this) = GetHead(o);
GetTail(*this) = GetTail(o);
return *this;
}
TAOCPP_ANNOTATION
tuple_impl& operator=(tuple_impl&& o)
{
GetHead(*this) = std::forward<Head>(GetHead(o));
GetTail(*this) = std::move(GetTail(o));
return *this;
}
template <typename... Ts>
TAOCPP_ANNOTATION tuple_impl& operator=(const tuple_impl<Idx, Ts...>& o)
{
GetHead(*this) = tuple_impl<Idx, Ts...>::GetHead(o);
GetTail(*this) = tuple_impl<Idx, Ts...>::GetTail(o);
return *this;
}
template <typename OHead, typename... OTailTs>
TAOCPP_ANNOTATION tuple_impl& operator=(tuple_impl<Idx, OHead, OTailTs...>&& o)
{
using OtherImpl = tuple_impl<Idx, OHead, OTailTs...>;
GetHead(*this) = std::forward<OHead>(OtherImpl::GetHead(o));
GetTail(*this) = std::move(OtherImpl::GetTail(o));
return *this;
}
static TAOCPP_ANNOTATION constexpr Head& GetHead(tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr const Head& GetHead(const tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<const Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr Tail& GetTail(tuple_impl& o) noexcept
{
return static_cast<Tail&>(o);
}
static TAOCPP_ANNOTATION constexpr const Tail& GetTail(const tuple_impl& o) noexcept
{
return static_cast<const Tail&>(o);
}
};
template <std::size_t Idx, typename HeadT>
class tuple_impl<Idx, HeadT> : private tuple_leaf<Idx, HeadT>
{
public:
template <std::size_t, typename...>
friend class tuple_impl;
using Leaf = tuple_leaf<Idx, HeadT>;
using Head = HeadT;
static const std::size_t Index = Idx;
TAOCPP_ANNOTATION constexpr tuple_impl()
: Leaf()
{
}
explicit TAOCPP_ANNOTATION constexpr tuple_impl(const HeadT& h)
: Leaf(h)
{
}
template <typename OHeadT>
explicit TAOCPP_ANNOTATION constexpr tuple_impl(OHeadT&& h)
: Leaf(std::forward<OHeadT>(h))
{
}
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl& o)
: Leaf(GetHead(o))
{
}
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl&& o)
: Leaf(std::forward<Head>(GetHead(o)))
{
}
template <typename OHeadT>
TAOCPP_ANNOTATION constexpr tuple_impl(const tuple_impl<Idx, OHeadT>& o)
: Leaf(tuple_impl<Idx, OHeadT>::GetHead(o))
{
}
template <typename OHeadT>
TAOCPP_ANNOTATION constexpr tuple_impl(tuple_impl<Idx, OHeadT>&& o)
: Leaf(std::forward<OHeadT>(tuple_impl<Idx, OHeadT>::GetHead(o)))
{
}
TAOCPP_ANNOTATION
tuple_impl& operator=(const tuple_impl& o)
{
GetHead(*this) = GetHead(o);
return *this;
}
TAOCPP_ANNOTATION
tuple_impl& operator=(tuple_impl&& o)
{
GetHead(*this) = std::forward<Head>(GetHead(o));
return *this;
}
template <typename OHeadT>
TAOCPP_ANNOTATION tuple_impl& operator=(const tuple_impl<Idx, OHeadT>& o)
{
GetHead(*this) = tuple_impl<Idx, OHeadT>::GetHead(o);
return *this;
}
template <typename OHeadT>
TAOCPP_ANNOTATION tuple_impl& operator=(tuple_impl<Idx, OHeadT>&& o)
{
using OtherImpl = tuple_impl<Idx, OHeadT>;
GetHead(*this) = std::forward<OHeadT>(OtherImpl::GetHead(o));
return *this;
}
static TAOCPP_ANNOTATION constexpr Head& GetHead(tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<Leaf&>(o));
}
static TAOCPP_ANNOTATION constexpr const Head& GetHead(const tuple_impl& o) noexcept
{
return Leaf::Get(static_cast<const Leaf&>(o));
}
};
template <std::size_t Idx, typename Head, typename... Tail>
TAOCPP_ANNOTATION constexpr Head& get_helper(tuple_impl<Idx, Head, Tail...>& t) noexcept
{
return tuple_impl<Idx, Head, Tail...>::GetHead(t);
}
template <std::size_t Idx, typename Head, typename... Tail>
TAOCPP_ANNOTATION constexpr const Head& get_helper(const tuple_impl<Idx, Head, Tail...>& t) noexcept
{
return tuple_impl<Idx, Head, Tail...>::GetHead(t);
}
// Unassignable stateless type:
struct ignore_impl
{
template <class T>
TAOCPP_ANNOTATION constexpr const ignore_impl& operator=(const T&) const
{
return *this;
}
};
} // end namespace detail
/// Reimplementation of std::tuple with markup for device support.
template <typename... Ts>
class tuple;
template <typename... Ts>
class tuple : public detail::tuple_impl<0, Ts...>
{
using Impl = detail::tuple_impl<0, Ts...>;
public:
TAOCPP_ANNOTATION constexpr tuple()
: Impl()
{
}
TAOCPP_ANNOTATION constexpr explicit tuple(const Ts&... ts)
: Impl(ts...)
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr explicit tuple(const OTs&... ts)
: Impl(ts...)
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr explicit tuple(OTs&&... ts)
: Impl(std::forward<OTs>(ts)...)
{
}
TAOCPP_ANNOTATION constexpr tuple(const tuple&) = default;
TAOCPP_ANNOTATION constexpr tuple(tuple&& o) = default;
template <typename... OTs>
TAOCPP_ANNOTATION constexpr tuple(const tuple<OTs...>& o)
: Impl(static_cast<detail::tuple_impl<0, OTs...>&>(o))
{
}
template <typename... OTs>
TAOCPP_ANNOTATION constexpr tuple(tuple<OTs...>&& o)
: Impl(static_cast<detail::tuple_impl<0, OTs...>&&>(o))
{
}
TAOCPP_ANNOTATION
tuple& operator=(const tuple& o)
{
this->Impl::operator=(o);
return *this;
}
TAOCPP_ANNOTATION
tuple& operator=(tuple&& o)
{
this->Impl::operator=(std::move(o));
return *this;
}
template <typename... OTs>
TAOCPP_ANNOTATION typename std::enable_if<sizeof...(Ts) == sizeof...(OTs), tuple&>::type
operator=(const tuple<OTs...>& o)
{
this->Impl::operator=(o);
return *this;
}
template <typename... OTs>
TAOCPP_ANNOTATION typename std::enable_if<sizeof...(Ts) == sizeof...(OTs), tuple&>::type
operator=(tuple<OTs...>&& o)
{
this->Impl::operator=(std::move(o));
return *this;
}
};
// Specialize for empty tuple:
template <>
class tuple<>
{
public:
tuple() = default;
};
/// Reimplementation of std::tuple_size with markup for device support.
template <typename TupleType>
struct tuple_size;
template <typename... Ts>
struct tuple_size<tuple<Ts...>>
: public std::integral_constant<std::size_t, static_cast<std::size_t>(sizeof...(Ts))>
{
static const std::size_t value = static_cast<std::size_t>(sizeof...(Ts));
};
/// Reimplementation of std::tuple_element with markup for device support.
template <std::size_t Idx, typename TupleType>
struct tuple_element;
template <std::size_t Idx, typename Head, typename... Tail>
struct tuple_element<Idx, tuple<Head, Tail...>> : public tuple_element<Idx - 1, tuple<Tail...>>
{
};
template <typename Head, typename... Tail>
struct tuple_element<0, tuple<Head, Tail...>>
{
using type = Head;
};
template <std::size_t Idx>
struct tuple_element<Idx, tuple<>>
{
static_assert(Idx < tuple_size<tuple<>>::value, "Tuple index valid.");
};
/// Reimplementation of std::get with markup for device support.
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr const typename tuple_element<Idx, tuple<Ts...>>::type& get(
const tuple<Ts...>& t) noexcept
{
return detail::get_helper<Idx>(t);
}
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr typename tuple_element<Idx, tuple<Ts...>>::type& get(
tuple<Ts...>& t) noexcept
{
return detail::get_helper<Idx>(t);
}
template <std::size_t Idx, typename... Ts>
TAOCPP_ANNOTATION constexpr typename tuple_element<Idx, tuple<Ts...>>::type&& get(
tuple<Ts...>&& t) noexcept
{
using ResultType = typename tuple_element<Idx, tuple<Ts...>>::type;
return std::forward<ResultType&&>(get<Idx>(t));
}
/// Reimplementation of std::make_tuple with markup for device support.
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple<typename std::decay<Ts>::type...> make_tuple(Ts... ts)
{
using ResultType = tuple<typename std::decay<Ts>::type...>;
return ResultType(std::forward<Ts>(ts)...);
}
/// Reimplementation of std::tie with markup for device support.
template <typename... Ts>
TAOCPP_ANNOTATION constexpr tuple<Ts&...> tie(Ts&... ts) noexcept
{
return tuple<Ts&...>(ts...);
}
/// Reimplementation of std::ignore with markup for device support.
static const detail::ignore_impl ignore{};
} // end namespace simple_tuple
#endif // SimpleTuple_h
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef Tuple_h
#define Tuple_h
// tao::tuple is a much more efficient tuple implementation, but it doesn't
// work on MSVC2015. For this compiler, fallback to a simpler implementation.
#if _MSC_VER == 1900
#define TAOCPP_USE_SIMPLE_TUPLE
#endif
#ifdef TAOCPP_USE_SIMPLE_TUPLE
#include "SimpleTuple.h"
#else
#include "tao/tuple/tuple.hpp"