Merge topic 'vtkm-tuple'

75a46dc2e Remove tao tuple from third party libraries
e05588a19 Add changelog for Tuple
f639e152d Fix ICE in VS 2015
625a6b4a9 Fix CUDA parse error
6f0edbec2 Move from tao::tuple to vtkm::Tuple
dca814434 Add vtkmstd::integer_sequence
5773ea3e1 Add porting layer for future std features
56636afc7 Make Tuple class

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1977
This commit is contained in:
Kenneth Moreland 2020-03-17 15:49:42 +00:00 committed by Kitware Robot
commit ac604d5673
50 changed files with 6768 additions and 3080 deletions

@ -104,7 +104,7 @@ function(do_verify root_dir prefix)
#Step 1. Setup the extensions to check, and all file and directory
# extensions
set(files_extensions
*.hpp #needed for diy and taotuple
*.hpp #needed for diy
*.h
*.hxx
)

@ -202,6 +202,7 @@ check_type_size("long long" VTKm_SIZE_LONG_LONG BUILTIN_TYPES_ONLY)
#-----------------------------------------------------------------------------
# Add subdirectories
add_subdirectory(vtkmstd)
add_subdirectory(vtkm)
#-----------------------------------------------------------------------------

@ -0,0 +1,14 @@
# Porting layer for future std features
Currently, VTK-m is using C++11. However, it is often useful to use
features in the `std` namespace that are defined for C++14 or later. We can
provide our own versions (sometimes), but it is preferable to use the
version provided by the compiler if available.
There were already some examples of defining portable versions of C++14 and
C++17 classes in a `vtkmstd` namespace, but these were sprinkled around the
source code.
There is now a top level `vtkmstd` directory and in it are header files
that provide portable versions of these future C++ classes. In each case,
preprocessor macros are used to select which version of the class to use.

220
docs/changelog/tuple.md Normal file

@ -0,0 +1,220 @@
# Add a vtkm::Tuple class
This change added a `vtkm::Tuple` class that is very similar in nature to
`std::tuple`. This should replace our use of tao tuple.
The motivation for this change was some recent attempts at removing objects
like `Invocation` and `FunctionInterface`. I expected these changes to
speed up the build, but in fact they ended up slowing down the build. I
believe the problem was that these required packing variable parameters
into a tuple. I was using the tao `tuple` class, but it seemed to slow down
the compile. (That is, compiling tao's `tuple` seemed much slower than
compiling the equivalent `FunctionInterface` class.)
The implementation of `vtkm::Tuple` is using `pyexpander` to build lots of
simple template cases for the object (with a backup implementation for even
longer argument lists). I believe the compiler is better and parsing
through thousands of lines of simple templates than to employ clever MPL to
build general templates.
## Usage
The `vtkm::Tuple` class is defined in the `vtkm::Tuple.h` header file. A
`Tuple` is designed to behave much like a `std::tuple` with some minor
syntax differences to fit VTK-m coding standards.
A tuple is declared with a list of template argument types.
``` cpp
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>> myTuple;
```
If given no arguments, a `vtkm::Tuple` will default-construct its contained
objects. A `vtkm::Tuple` can also be constructed with the initial values of
all contained objects.
``` cpp
vtkm::Tuple<vtkm::Id, vtkm::Vec3f, vtkm::cont::ArrayHandle<vtkm::Float32>>
myTuple(0, vtkm::Vec3f(0, 1, 2), array);
```
For convenience there is a `vtkm::MakeTuple` function that takes arguments
and packs them into a `Tuple` of the appropriate type. (There is also a
`vtkm::make_tuple` alias to the function to match the `std` version.)
``` cpp
auto myTuple = vtkm::MakeTuple(0, vtkm::Vec3f(0, 1, 2), array);
```
Data is retrieved from a `Tuple` by using the `vtkm::Get` method. The `Get`
method is templated on the index to get the value from. The index is of
type `vtkm::IdComponent`. (There is also a `vtkm::get` that uses a
`std::size_t` as the index type as an alias to the function to match the
`std` version.)
``` cpp
vtkm::Id a = vtkm::Get<0>(myTuple);
vtkm::Vec3f b = vtkm::Get<1>(myTuple);
vtkm::cont::ArrayHandle<vtkm::Float32> c = vtkm::Get<2>(myTuple);
```
Likewise `vtkm::TupleSize` and `vtkm::TupleElement` (and their aliases
`vtkm::Tuple_size`, `vtkm::tuple_element`, and `vtkm::tuple_element_t`) are
provided.
## Extended Functionality
The `vtkm::Tuple` class contains some functionality beyond that of
`std::tuple` to cover some common use cases in VTK-m that are tricky to
implement. In particular, these methods allow you to use a `Tuple` as you
would commonly use parameter packs. This allows you to stash parameter
packs in a `Tuple` and then get them back out again.
### For Each
`vtkm::Tuple::ForEach()` is a method that takes a function or functor and
calls it for each of the items in the tuple. Nothing is returned from
`ForEach` and any return value from the function is ignored.
`ForEach` can be used to check the validity of each item.
``` cpp
void CheckPositive(vtkm::Float64 x)
{
if (x < 0)
{
throw vtkm::cont::ErrorBadValue("Values need to be positive.");
}
}
// ...
vtkm::Tuple<vtkm::Float64, vtkm::Float64, vtkm::Float64> tuple(
CreateValue1(), CreateValue2(), CreateValue3());
// Will throw an error if any of the values are negative.
tuple.ForEach(CheckPositive);
```
`ForEach` can also be used to aggregate values.
``` cpp
struct SumFunctor
{
vtkm::Float64 Sum = 0;
template <typename T>
void operator()(const T& x)
{
this->Sum = this->Sum + static_cast<vtkm::Float64>(x);
}
};
// ...
vtkm::Tuple<vtkm::Float32, vtkm::Float64, vtkm::Id> tuple(
CreateValue1(), CreateValue2(), CreateValue3());
SumFunctor sum;
tuple.ForEach(sum);
vtkm::Float64 average = sum.Sum / 3;
```
### Transform
`vtkm::Tuple::Transform` is a method that builds a new `Tuple` by calling a
function or functor on each of the items. The return value is placed in the
corresponding part of the resulting `Tuple`, and the type is automatically
created from the return type of the function.
``` cpp
struct GetReadPortalFunctor
{
template <typename Array>
typename Array::ReadPortal operator()(const Array& array) const
{
VTKM_IS_ARRAY_HANDLE(Array);
return array.ReadPortal();
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
auto portalTuple = arrayTuple.Transform(GetReadPortalFunctor{});
```
### Apply
`vtkm::Tuple::Apply` is a method that calls a function or functor using the
objects in the `Tuple` as the arguments. If the function returns a value,
that value is returned from `Apply`.
``` cpp
struct AddArraysFunctor
{
template <typename Array1, typename Array2, typename Array3>
vtkm::Id operator()(Array1 inArray1, Array2 inArray2, Array3 outArray) const
{
VTKM_IS_ARRAY_HANDLE(Array1);
VTKM_IS_ARRAY_HANDLE(Array2);
VTKM_IS_ARRAY_HANDLE(Array3);
vtkm::Id length = inArray1.GetNumberOfValues();
VTKM_ASSERT(inArray2.GetNumberOfValues() == length);
outArray.Allocate(length);
auto inPortal1 = inArray1.ReadPortal();
auto inPortal2 = inArray2.ReadPortal();
auto outPortal = outArray.WritePortal();
for (vtkm::Id index = 0; index < length; ++index)
{
outPortal.Set(index, inPortal1.Get(index) + inPortal2.Get(index));
}
return length;
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
vtkm::Id arrayLength = arrayTuple.Apply(AddArraysFunctor{});
```
If additional arguments are given to `Apply`, they are also passed to the
function (before the objects in the `Tuple`). This is helpful for passing
state to the function. (This feature is not available in either `ForEach`
or `Transform` for technical implementation reasons.)
``` cpp
struct ScanArrayLengthFunctor
{
template <std::size_t N, typename Array, typename... Remaining>
std::array<vtkm::Id, N + 1 + sizeof...(Remaining)>
operator()(const std::array<vtkm::Id, N>& partialResult,
const Array& nextArray,
const Remaining&... remainingArrays) const
{
std::array<vtkm::Id, N + 1> nextResult;
std::copy(partialResult.begin(), partialResult.end(), nextResult.begin());
nextResult[N] = nextResult[N - 1] + nextArray.GetNumberOfValues();
return (*this)(nextResult, remainingArray);
}
template <std::size_t N>
std::array<vtkm::Id, N> operator()(const std::array<vtkm::Id, N>& result) const
{
return result;
}
};
// ...
auto arrayTuple = vtkm::MakeTuple(array1, array2, array3);
std::array<vtkm::Id, 4> =
arrayTuple.Apply(ScanArrayLengthFunctor{}, std::array<vtkm::Id, 1>{ 0 });
```

@ -47,6 +47,7 @@ set(headers
Swap.h
TopologyElementTag.h
Transform3D.h
Tuple.h
TypeList.h
TypeListTag.h
Types.h
@ -67,6 +68,7 @@ set(template_sources
)
vtkm_pyexpander_generated_file(Math.h)
vtkm_pyexpander_generated_file(Tuple.h)
vtkm_declare_headers(
${headers}
@ -81,7 +83,6 @@ if(VTKm_ENABLE_LOGGING)
add_subdirectory(thirdparty/loguru)
endif()
add_subdirectory(thirdparty/optionparser)
add_subdirectory(thirdparty/taotuple)
add_subdirectory(thirdparty/lcl)
add_subdirectory(testing)

4904
vtkm/Tuple.h Normal file

File diff suppressed because it is too large Load Diff

504
vtkm/Tuple.h.in Normal file

@ -0,0 +1,504 @@
//============================================================================
// 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.
//============================================================================
$# This file uses the pyexpander macro processing utility to build the
$# FunctionInterface facilities that use a variable number of arguments.
$# Information, documentation, and downloads for pyexpander can be found at:
$#
$# http://pyexpander.sourceforge.net/
$#
$# To build the source code, execute the following (after installing
$# pyexpander, of course):
$#
$# expander.py VariantDetail.h.in > VariantDetail.h
$#
$# Ignore the following comment. It is meant for the generated file.
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by Tuple.h.in
#ifndef vtk_m_Tuple_h
#define vtk_m_Tuple_h
#include <vtkm/Types.h>
#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/internal/IndexTag.h>
$py(max_expanded=20)\
$# Python commands used in template expansion.
$py(
def type_list(num_params, name='T'):
if num_params < 1:
return ''
result = '%s0' % name
for param in range(1, num_params):
result += ', %s%d' % (name, param)
return result
def typename_list(num_params, name='T'):
if num_params < 1:
return ''
result = 'typename %s0' % name
for param in range(1, num_params):
result += ', typename %s%d' % (name, param)
return result
def perfect_param_list(num_params, classname='A', argname='a'):
if num_params < 1:
return ''
result = '%s0&& %s0' % (classname, argname)
for param in range(1, num_params):
result += ', %s%d&& %s%d' % (classname, param, argname, param)
return result
)\
$#
$extend(type_list, typename_list, perfect_param_list)\
namespace vtkm
{
///@{
/// \brief VTK-m replacement for std::tuple
///
/// This function serves the same function as `std::tuple` and behaves similarly. However, this
/// version of `Tuple` works on devices that VTK-m supports. There are also some implementation
/// details that makes compiling faster for VTK-m use. We also provide some methods like `Apply`
/// and `ForEach` that are helpful for several VTK-m operations.
///
template <typename... Ts>
class Tuple;
/// \brief Get the size of a tuple.
///
/// Given a `vtkm::Tuple` type, because a `std::integral_constant` of the type.
///
template <typename TupleType>
using TupleSize = std::integral_constant<vtkm::IdComponent, TupleType::Size>;
/// \brief Compatible with `std::tuple_size` for `vtkm::Tuple`.
///
template <typename TupleType>
using tuple_size = std::integral_constant<std::size_t, static_cast<std::size_t>(TupleType::Size)>;
namespace detail
{
template <vtkm::IdComponent Index, typename TupleType>
struct TupleElementImpl
{
using type = decltype(TupleType::ElementTypeI(vtkm::internal::IndexTag<Index>{}));
};
} // namespace detail
/// \brief Becomes the type of the given index for the given `vtkm::Tuple`.
///
template <vtkm::IdComponent Index, typename TupleType>
using TupleElement = typename detail::TupleElementImpl<Index, TupleType>::type;
/// \brief Compatible with `std::tuple_element` for `vtkm::Tuple`.
///
template <std::size_t Index, typename TupleType>
struct tuple_element
{
using type = TupleElement<static_cast<vtkm::IdComponent>(Index), TupleType>;
};
/// \brief Compatible with `std::tuple_element_t` for `vtkm::Tuple`.
///
template <std::size_t Index, typename TupleType>
using tuple_element_t = typename tuple_element<Index, TupleType>::type;
///@{
/// \brief Retrieve the object from a `vtkm::Tuple` at the given index.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
{
return tuple.template Get<Index>();
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
{
return tuple.template Get<Index>();
}
///@}
///@{
/// \brief Compatible with `std::get` for `vtkm::Tuple`.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
-> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
-> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
///@}
/// \brief Creates a new `vtkm::Tuple` with the given types.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto MakeTuple(Ts&&... args) -> vtkm::Tuple<typename std::decay<Ts>::type...>
{
return vtkm::Tuple<typename std::decay<Ts>::type...>(std::forward<Ts>(args)...);
}
/// \brief Compatible with `std::make_tuple` for `vtkm::Tuple`.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto make_tuple(Ts&&... args) -> decltype(vtkm::MakeTuple(std::forward<Ts>(args)...))
{
return vtkm::MakeTuple(std::forward<Ts>(args)...);
}
namespace detail
{
struct TupleTransformFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Ts>
VTKM_EXEC_CONT auto operator()(Function&& f, Ts&&... args)
-> decltype(vtkm::MakeTuple(f(std::forward<Ts>(args))...))
{
return vtkm::MakeTuple(f(std::forward<Ts>(args))...);
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleTransform(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f));
}
struct TupleForEachFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Ts>
VTKM_EXEC_CONT void operator()(Function&& f, Ts&&... args)
{
(void)std::initializer_list<bool>{ (f(std::forward<Ts>(args)), false)... };
}
};
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleForEach(TupleType&& tuple, Function&& f)
-> decltype(tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f)))
{
return tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f));
}
} // namespace detail
template <>
class Tuple<>
{
public:
static constexpr vtkm::IdComponent Size = 0;
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args)
-> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args) const
-> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&&) const
{
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT vtkm::Tuple<> Transform(Function&&) const
{
return vtkm::Tuple<>{};
}
};
// clang-format off
$for(num_params in range(1, max_expanded + 1))\
template<$typename_list(num_params)>
class Tuple<$type_list(num_params)>
{
$for(index in range(0, num_params))\
T$(index) Value$(index);
static T$(index) ElementTypeI(vtkm::internal::IndexTag<$(index)>);
VTKM_EXEC_CONT vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>)
{
return this->Value$(index);
}
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>) const
{
return this->Value$(index);
}
$endfor\
// Invalid indices
template <vtkm::IdComponent Index>
static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);
template <vtkm::IdComponent, typename>
friend struct detail::TupleElementImpl;
public:
static constexpr vtkm::IdComponent Size = $(num_params);
template <vtkm::IdComponent Index>
using ElementType = vtkm::TupleElement<Index, Tuple<$type_list(num_params)>>;
Tuple() = default;
Tuple(Tuple&&) = default;
Tuple(const Tuple&) = default;
~Tuple() = default;
Tuple& operator=(Tuple&&) = default;
Tuple& operator=(const Tuple&) = default;
VTKM_SUPPRESS_EXEC_WARNINGS
template <$typename_list(num_params, 'A')>
VTKM_EXEC_CONT Tuple($perfect_param_list(num_params, 'A', 'a'))
: Value0(std::forward<A0>(a0))
$for(index in range(1, num_params))\
, Value$(index)(std::forward<A$(index)>(a$(index)))
$endfor\
{
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args)
-> decltype(f(std::forward<Args>(args)..., $type_list(num_params, "Value")))
{
return f(std::forward<Args>(args)..., $type_list(num_params, "Value"));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args) const
-> decltype(f(std::forward<Args>(args)..., $type_list(num_params, "Value")))
{
return f(std::forward<Args>(args)..., $type_list(num_params, "Value"));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
};
$endfor\
// Fallback case for tuples with > $(max_expanded) items.
template<$typename_list(max_expanded + 1), typename... Ts>
class Tuple<$type_list(max_expanded + 1), Ts...>
{
$for(index in range(0, max_expanded))\
T$(index) Value$(index);
static T$(index) ElementTypeI(vtkm::internal::IndexTag<$(index)>);
VTKM_EXEC_CONT vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>)
{
return this->Value$(index);
}
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T$(index)>& GetImpl(vtkm::internal::IndexTag<$(index)>) const
{
return this->Value$(index);
}
$endfor\
// Implement the "extra" objects in a sub-Tuple
using RemainingValuesType = vtkm::Tuple<T$(max_expanded), Ts...>;
RemainingValuesType RemainingValues;
template <vtkm::IdComponent Index>
static vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>
ElementTypeI(vtkm::internal::IndexTag<Index>);
template <typename vtkm::IdComponent Index>
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>>&
GetImpl(vtkm::internal::IndexTag<Index>) { return vtkm::Get<Index - $(max_expanded)>(this->RemainingValues); }
template <typename vtkm::IdComponent Index>
VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - $(max_expanded), RemainingValuesType>>&
GetImpl(vtkm::internal::IndexTag<Index>) const { return vtkm::Get<Index - $(max_expanded)>(this->RemainingValues); }
template <vtkm::IdComponent, typename>
friend struct detail::TupleElementImpl;
public:
static constexpr vtkm::IdComponent Size =
$(max_expanded + 1) + static_cast<vtkm::IdComponent>(sizeof...(Ts));
template <vtkm::IdComponent Index>
using ElementType = vtkm::TupleElement<Index, Tuple<$type_list(max_expanded + 1), Ts...>>;
Tuple() = default;
Tuple(Tuple&&) = default;
Tuple(const Tuple&) = default;
~Tuple() = default;
Tuple& operator=(Tuple&&) = default;
Tuple& operator=(const Tuple&) = default;
VTKM_SUPPRESS_EXEC_WARNINGS
template <$typename_list(max_expanded, 'A'), typename... As>
VTKM_EXEC_CONT Tuple($perfect_param_list(max_expanded, 'A', 'a'), As&&... remainingArgs)
: Value0(std::forward<A0>(a0))
$for(index in range(1, max_expanded))\
, Value$(index)(std::forward<A$(index)>(a$(index)))
$endfor\
, RemainingValues(std::forward<As>(remainingArgs)...)
{
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
template <vtkm::IdComponent Index>
VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
{
return this->GetImpl(vtkm::internal::IndexTag<Index>{});
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args)
-> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1)))
{
return this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function, typename... Args>
VTKM_EXEC_CONT
auto Apply(Function&& f, Args&&... args) const
-> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1)))
{
return this->RemainingValues.Apply(std::forward<Function>(f),
std::forward<Args>(args)...,
$for(index in range(0, max_expanded - 1))\
this->Value$(index),
$endfor\
this->Value$(max_expanded - 1));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f)
{
detail::TupleForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT void ForEach(Function&& f) const
{
detail::TupleForEach(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f)
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Function>
VTKM_EXEC_CONT auto Transform(Function&& f) const
-> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
{
return detail::TupleTransform(*this, std::forward<Function>(f));
}
};
///@}
// clang-format on
} // namespace vtkm
#endif //vtk_m_Tuple_h

@ -14,12 +14,13 @@
#include <vtkm/Deprecated.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Tuple.h>
#include <vtkm/VecTraits.h>
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkm/internal/brigand.hpp>
#include <vtkmstd/integer_sequence.h>
#include <type_traits>
namespace vtkm
@ -61,278 +62,162 @@ struct AllAreArrayHandles
};
// GetValueType: ---------------------------------------------------------------
// Determines the output ValueType of the objects in TupleType, a vtkmstd::tuple
// which can contain ArrayHandles, ArrayPortals...anything with a ValueType
// defined, really. For example, if the input TupleType contains 3 types with
// Float32 ValueTypes, then the ValueType defined here will be Vec<Float32, 3>.
// This also validates that all members have the same ValueType.
template <typename TupleType>
struct GetValueTypeImpl;
// Determines the output `ValueType` of the set of `ArrayHandle` objects. For example, if the input
// set contains 3 types with `vtkm::Float32` ValueTypes, then the ValueType defined here will be
// `vtkm::Vec<Float32, 3>`. This also validates that all members have the same `ValueType`.
template <typename Head, typename... Tail>
struct GetValueTypeImpl<vtkmstd::tuple<Head, Tail...>>
template <typename ExpectedValueType, typename ArrayType>
constexpr bool CheckValueType()
{
using Type = typename Head::ValueType;
private:
using Next = GetValueTypeImpl<vtkmstd::tuple<Tail...>>;
VTKM_STATIC_ASSERT_MSG(VTKM_PASS_COMMAS(std::is_same<Type, typename Next::Type>::value),
VTKM_STATIC_ASSERT_MSG((std::is_same<ExpectedValueType, typename ArrayType::ValueType>::value),
"ArrayHandleCompositeVector must be built from "
"ArrayHandles with the same ValueTypes.");
};
return std::is_same<ExpectedValueType, typename ArrayType::ValueType>::value;
}
template <typename Head>
struct GetValueTypeImpl<vtkmstd::tuple<Head>>
{
using Type = typename Head::ValueType;
};
template <typename TupleType>
template <typename ArrayType0, typename... ArrayTypes>
struct GetValueType
{
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<TupleType>::value >= 1);
static const vtkm::IdComponent COUNT =
static_cast<vtkm::IdComponent>(vtkmstd::tuple_size<TupleType>::value);
using ComponentType = typename GetValueTypeImpl<TupleType>::Type;
static constexpr vtkm::IdComponent COUNT =
static_cast<vtkm::IdComponent>(sizeof...(ArrayTypes)) + 1;
using ComponentType = typename ArrayType0::ValueType;
static constexpr std::array<bool, sizeof...(ArrayTypes) + 1> ValueCheck{
{ true, CheckValueType<ComponentType, ArrayTypes>()... }
};
using ValueType = vtkm::Vec<ComponentType, COUNT>;
};
// TupleTypePrepend: -----------------------------------------------------------
// Prepend a type to a tuple, defining the new tuple in Type.
template <typename PrependType, typename TupleType>
struct TupleTypePrepend;
template <typename PrependType, typename... TupleTypes>
struct TupleTypePrepend<PrependType, vtkmstd::tuple<TupleTypes...>>
// Special case for only one component
template <typename ArrayType>
struct GetValueType<ArrayType>
{
using Type = vtkmstd::tuple<PrependType, TupleTypes...>;
static constexpr vtkm::IdComponent COUNT = 1;
using ComponentType = typename ArrayType::ValueType;
using ValueType = typename ArrayType::ValueType;
};
// ArrayTupleForEach: ----------------------------------------------------------
// Collection of methods that iterate through the arrays in ArrayTuple to
// implement the ArrayHandle API.
template <std::size_t Index, std::size_t Count, typename ArrayTuple>
struct ArrayTupleForEach
// -----------------------------------------------------------------------------
// Functors to access Storage methods. This is used with vtkm::Tuple's
// ForEach and Transform methods.
struct WritePortal
{
using Next = ArrayTupleForEach<Index + 1, Count, ArrayTuple>;
template <typename PortalTuple>
VTKM_CONT static void GetPortalTupleControl(ArrayTuple& arrays, PortalTuple& portals)
template <typename ArrayHandle>
typename ArrayHandle::WritePortalType operator()(const ArrayHandle& array) const
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).WritePortal();
Next::GetPortalTupleControl(arrays, portals);
}
template <typename PortalTuple>
VTKM_CONT static void GetPortalConstTupleControl(const ArrayTuple& arrays, PortalTuple& portals)
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).ReadPortal();
Next::GetPortalConstTupleControl(arrays, portals);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInput(const ArrayTuple& arrays,
PortalTuple& portals,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) = vtkmstd::get<Index>(arrays).PrepareForInput(DeviceTag(), token);
Next::template PrepareForInput<DeviceTag>(arrays, portals, token);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInPlace(ArrayTuple& arrays,
PortalTuple& portals,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) =
vtkmstd::get<Index>(arrays).PrepareForInPlace(DeviceTag(), token);
Next::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForOutput(ArrayTuple& arrays,
PortalTuple& portals,
vtkm::Id numValues,
vtkm::cont::Token& token)
{
vtkmstd::get<Index>(portals) =
vtkmstd::get<Index>(arrays).PrepareForOutput(numValues, DeviceTag(), token);
Next::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
}
VTKM_CONT
static void Allocate(ArrayTuple& arrays, vtkm::Id numValues)
{
vtkmstd::get<Index>(arrays).Allocate(numValues);
Next::Allocate(arrays, numValues);
}
VTKM_CONT
static void Shrink(ArrayTuple& arrays, vtkm::Id numValues)
{
vtkmstd::get<Index>(arrays).Shrink(numValues);
Next::Shrink(arrays, numValues);
}
VTKM_CONT
static void ReleaseResources(ArrayTuple& arrays)
{
vtkmstd::get<Index>(arrays).ReleaseResources();
Next::ReleaseResources(arrays);
return array.WritePortal();
}
};
template <std::size_t Index, typename ArrayTuple>
struct ArrayTupleForEach<Index, Index, ArrayTuple>
struct ReadPortal
{
template <typename PortalTuple>
VTKM_CONT static void GetPortalTupleControl(ArrayTuple&, PortalTuple&)
template <typename ArrayHandle>
typename ArrayHandle::ReadPortalType operator()(const ArrayHandle& array) const
{
return array.ReadPortal();
}
template <typename PortalTuple>
VTKM_CONT static void GetPortalConstTupleControl(const ArrayTuple&, PortalTuple&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInput(const ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForInPlace(ArrayTuple&, PortalTuple&, vtkm::cont::Token&)
{
}
template <typename DeviceTag, typename PortalTuple>
VTKM_CONT static void PrepareForOutput(ArrayTuple&, PortalTuple&, vtkm::Id, vtkm::cont::Token&)
{
}
VTKM_CONT static void Allocate(ArrayTuple&, vtkm::Id) {}
VTKM_CONT static void Shrink(ArrayTuple&, vtkm::Id) {}
VTKM_CONT static void ReleaseResources(ArrayTuple&) {}
};
// PortalTupleTraits: ----------------------------------------------------------
// Determine types of ArrayHandleCompositeVector portals and construct the
// portals from the input arrays.
template <typename ArrayTuple>
struct PortalTupleTypeGeneratorImpl;
template <typename Head, typename... Tail>
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head, Tail...>>
struct Allocate
{
using Next = PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Tail...>>;
using PortalControlTuple = typename TupleTypePrepend<typename Head::WritePortalType,
typename Next::PortalControlTuple>::Type;
using PortalConstControlTuple =
typename TupleTypePrepend<typename Head::ReadPortalType,
typename Next::PortalConstControlTuple>::Type;
template <typename DeviceTag>
struct ExecutionTypes
vtkm::Id NumValues;
VTKM_CONT Allocate(vtkm::Id numValues)
: NumValues(numValues)
{
using PortalTuple = typename TupleTypePrepend<
typename Head::template ExecutionTypes<DeviceTag>::Portal,
typename Next::template ExecutionTypes<DeviceTag>::PortalTuple>::Type;
using PortalConstTuple = typename TupleTypePrepend<
typename Head::template ExecutionTypes<DeviceTag>::PortalConst,
typename Next::template ExecutionTypes<DeviceTag>::PortalConstTuple>::Type;
};
}
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
array.Allocate(this->NumValues);
}
};
template <typename Head>
struct PortalTupleTypeGeneratorImpl<vtkmstd::tuple<Head>>
struct Shrink
{
using PortalControlTuple = vtkmstd::tuple<typename Head::WritePortalType>;
using PortalConstControlTuple = vtkmstd::tuple<typename Head::ReadPortalType>;
template <typename DeviceTag>
struct ExecutionTypes
vtkm::Id NumValues;
VTKM_CONT Shrink(vtkm::Id numValues)
: NumValues(numValues)
{
using PortalTuple = vtkmstd::tuple<typename Head::template ExecutionTypes<DeviceTag>::Portal>;
using PortalConstTuple =
vtkmstd::tuple<typename Head::template ExecutionTypes<DeviceTag>::PortalConst>;
};
}
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
array.Shrink(this->NumValues);
}
};
template <typename ArrayTuple>
struct PortalTupleTraits
struct ReleaseResources
{
private:
using TypeGenerator = PortalTupleTypeGeneratorImpl<ArrayTuple>;
using ForEachArray = ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
public:
using PortalTuple = typename TypeGenerator::PortalControlTuple;
using PortalConstTuple = typename TypeGenerator::PortalConstControlTuple;
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalTuple>::value);
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalConstTuple>::value);
template <typename DeviceTag>
struct ExecutionTypes
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
using PortalTuple = typename TypeGenerator::template ExecutionTypes<DeviceTag>::PortalTuple;
using PortalConstTuple =
typename TypeGenerator::template ExecutionTypes<DeviceTag>::PortalConstTuple;
array.ReleaseResources();
}
};
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalTuple>::value);
VTKM_STATIC_ASSERT(vtkmstd::tuple_size<ArrayTuple>::value ==
vtkmstd::tuple_size<PortalConstTuple>::value);
};
// -----------------------------------------------------------------------------
// Functors to access ArrayTransfer methods. This is used with vtkm::Tuple's
// ForEach and Transform methods.
VTKM_CONT
static const PortalTuple GetPortalTupleControl(ArrayTuple& arrays)
template <typename Device>
struct PrepareForInput
{
vtkm::cont::Token& Token;
VTKM_CONT PrepareForInput(vtkm::cont::Token& token)
: Token(token)
{
PortalTuple portals;
ForEachArray::GetPortalTupleControl(arrays, portals);
return portals;
}
VTKM_CONT
static const PortalConstTuple GetPortalConstTupleControl(const ArrayTuple& arrays)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::PortalConst operator()(
const Array& array)
{
return array.PrepareForInput(Device{}, this->Token);
}
};
template <typename Device>
struct PrepareForInPlace
{
vtkm::cont::Token& Token;
VTKM_CONT PrepareForInPlace(vtkm::cont::Token& token)
: Token(token)
{
PortalConstTuple portals;
ForEachArray::GetPortalConstTupleControl(arrays, portals);
return portals;
}
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalConstTuple PrepareForInput(
const ArrayTuple& arrays,
vtkm::cont::Token& token)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::Portal operator()(Array& array)
{
return array.PrepareForInPlace(Device{}, this->Token);
}
};
template <typename Device>
struct PrepareForOutput
{
vtkm::Id NumValues;
vtkm::cont::Token& Token;
VTKM_CONT PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token)
: NumValues(numValues)
, Token(token)
{
typename ExecutionTypes<DeviceTag>::PortalConstTuple portals;
ForEachArray::template PrepareForInput<DeviceTag>(arrays, portals, token);
return portals;
}
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple PrepareForInPlace(
ArrayTuple& arrays,
vtkm::cont::Token& token)
template <typename Array>
VTKM_CONT typename Array::template ExecutionTypes<Device>::Portal operator()(Array& array)
{
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
ForEachArray::template PrepareForInPlace<DeviceTag>(arrays, portals, token);
return portals;
return array.PrepareForOutput(this->NumValues, Device{}, this->Token);
}
};
template <typename DeviceTag>
VTKM_CONT static const typename ExecutionTypes<DeviceTag>::PortalTuple
PrepareForOutput(ArrayTuple& arrays, vtkm::Id numValues, vtkm::cont::Token& token)
struct ReleaseResourcesExecution
{
template <typename Array>
VTKM_CONT void operator()(Array& array)
{
typename ExecutionTypes<DeviceTag>::PortalTuple portals;
ForEachArray::template PrepareForOutput<DeviceTag>(arrays, portals, numValues, token);
return portals;
array.ReleaseResourcesExecution();
}
};
@ -347,7 +232,7 @@ struct ArraySizeValidatorImpl
VTKM_CONT
static bool Exec(const TupleType& tuple, vtkm::Id numVals)
{
return vtkmstd::get<Index>(tuple).GetNumberOfValues() == numVals && Next::Exec(tuple, numVals);
return vtkm::Get<Index>(tuple).GetNumberOfValues() == numVals && Next::Exec(tuple, numVals);
}
};
@ -364,113 +249,96 @@ struct ArraySizeValidator
VTKM_CONT
static bool Exec(const TupleType& tuple, vtkm::Id numVals)
{
return ArraySizeValidatorImpl<0, vtkmstd::tuple_size<TupleType>::value, TupleType>::Exec(
tuple, numVals);
return ArraySizeValidatorImpl<0, vtkm::TupleSize<TupleType>::value, TupleType>::Exec(tuple,
numVals);
}
};
template <typename PortalList>
template <typename... PortalList>
using AllPortalsAreWritable =
typename brigand::all<PortalList,
typename brigand::all<brigand::list<PortalList...>,
brigand::bind<vtkm::internal::PortalSupportsSets, brigand::_1>>::type;
// GetFromPortals: -------------------------------------------------------------
// Given a set of array portals as arguments, returns a Vec comprising the values
// at the provided index.
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Portals>
VTKM_EXEC_CONT typename GetValueType<Portals...>::ValueType GetFromPortals(
vtkm::Id index,
const Portals&... portals)
{
return { portals.Get(index)... };
}
// SetToPortals: ---------------------------------------------------------------
// Given a Vec-like object, and index, and a set of array portals, sets each of
// the portals to the respective component of the Vec.
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ValueType, vtkm::IdComponent... I, typename... Portals>
VTKM_EXEC_CONT void SetToPortalsImpl(vtkm::Id index,
const ValueType& value,
vtkmstd::integer_sequence<vtkm::IdComponent, I...>,
const Portals&... portals)
{
using Traits = vtkm::VecTraits<ValueType>;
(void)std::initializer_list<bool>{ (portals.Set(index, Traits::GetComponent(value, I)),
false)... };
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ValueType, typename... Portals>
VTKM_EXEC_CONT void SetToPortals(vtkm::Id index, const ValueType& value, const Portals&... portals)
{
SetToPortalsImpl(
index,
value,
vtkmstd::make_integer_sequence<vtkm::IdComponent, vtkm::IdComponent(sizeof...(Portals))>{},
portals...);
}
} // end namespace compvec
template <typename PortalTuple>
template <typename... PortalTypes>
class VTKM_ALWAYS_EXPORT ArrayPortalCompositeVector
{
using Writable = compvec::AllPortalsAreWritable<PortalTuple>;
using Writable = compvec::AllPortalsAreWritable<PortalTypes...>;
using TupleType = vtkm::Tuple<PortalTypes...>;
TupleType Portals;
public:
using ValueType = typename compvec::GetValueType<PortalTuple>::ValueType;
using ValueType = typename compvec::GetValueType<PortalTypes...>::ValueType;
private:
using Traits = vtkm::VecTraits<ValueType>;
// Get: ----------------------------------------------------------------------
template <vtkm::IdComponent VectorIndex, typename PortalTupleT>
struct GetImpl;
template <vtkm::IdComponent VectorIndex, typename Head, typename... Tail>
struct GetImpl<VectorIndex, vtkmstd::tuple<Head, Tail...>>
{
using Next = GetImpl<VectorIndex + 1, vtkmstd::tuple<Tail...>>;
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, ValueType& vec, vtkm::Id arrayIndex)
{
Traits::SetComponent(vec, VectorIndex, vtkmstd::get<VectorIndex>(portals).Get(arrayIndex));
Next::Exec(portals, vec, arrayIndex);
}
};
template <vtkm::IdComponent VectorIndex, typename Head>
struct GetImpl<VectorIndex, vtkmstd::tuple<Head>>
{
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, ValueType& vec, vtkm::Id arrayIndex)
{
Traits::SetComponent(vec, VectorIndex, vtkmstd::get<VectorIndex>(portals).Get(arrayIndex));
}
};
// Set: ----------------------------------------------------------------------
template <vtkm::IdComponent VectorIndex, typename PortalTupleT>
struct SetImpl;
template <vtkm::IdComponent VectorIndex, typename Head, typename... Tail>
struct SetImpl<VectorIndex, vtkmstd::tuple<Head, Tail...>>
{
using Next = SetImpl<VectorIndex + 1, vtkmstd::tuple<Tail...>>;
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, const ValueType& vec, vtkm::Id arrayIndex)
{
vtkmstd::get<VectorIndex>(portals).Set(arrayIndex, Traits::GetComponent(vec, VectorIndex));
Next::Exec(portals, vec, arrayIndex);
}
};
template <vtkm::IdComponent VectorIndex, typename Head>
struct SetImpl<VectorIndex, vtkmstd::tuple<Head>>
{
VTKM_EXEC_CONT
static void Exec(const PortalTuple& portals, const ValueType& vec, vtkm::Id arrayIndex)
{
vtkmstd::get<VectorIndex>(portals).Set(arrayIndex, Traits::GetComponent(vec, VectorIndex));
}
};
public:
VTKM_EXEC_CONT
ArrayPortalCompositeVector() {}
VTKM_CONT
ArrayPortalCompositeVector(const PortalTuple& portals)
ArrayPortalCompositeVector(const PortalTypes&... portals)
: Portals(portals...)
{
}
VTKM_CONT
ArrayPortalCompositeVector(const TupleType& portals)
: Portals(portals)
{
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return vtkmstd::get<0>(this->Portals).GetNumberOfValues(); }
vtkm::Id GetNumberOfValues() const { return vtkm::Get<0>(this->Portals).GetNumberOfValues(); }
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const
{
ValueType result;
GetImpl<0, PortalTuple>::Exec(this->Portals, result, index);
return result;
return this->Portals.Apply(compvec::GetFromPortals<PortalTypes...>, index);
}
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
SetImpl<0, PortalTuple>::Exec(this->Portals, value, index);
this->Portals.Apply(compvec::SetToPortals<ValueType, PortalTypes...>, index, value);
}
private:
PortalTuple Portals;
};
} // namespace internal
@ -483,12 +351,6 @@ struct VTKM_ALWAYS_EXPORT StorageTagCompositeVec
namespace internal
{
template <typename ArrayTuple>
struct VTKM_ALWAYS_EXPORT VTKM_DEPRECATED(1.6, "Use StorageTagCompositeVec instead.")
StorageTagCompositeVector
{
};
template <typename... ArrayTs>
struct CompositeVectorTraits
{
@ -499,38 +361,27 @@ struct CompositeVectorTraits
"Template parameters for ArrayHandleCompositeVector "
"must be a list of ArrayHandle types.");
using ValueType = typename compvec::GetValueType<vtkmstd::tuple<ArrayTs...>>::ValueType;
using ValueType = typename compvec::GetValueType<ArrayTs...>::ValueType;
using StorageTag = vtkm::cont::StorageTagCompositeVec<typename ArrayTs::StorageTag...>;
using StorageType = Storage<ValueType, StorageTag>;
using Superclass = ArrayHandle<ValueType, StorageTag>;
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... Arrays>
class Storage<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>>
: CompositeVectorTraits<Arrays...>::StorageType
{
using Superclass = typename CompositeVectorTraits<Arrays...>::StorageType;
using Superclass::Superclass;
};
VTKM_DEPRECATED_SUPPRESS_END
template <typename T, typename... StorageTags>
class Storage<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
vtkm::cont::StorageTagCompositeVec<StorageTags...>>
{
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
using ForEachArray =
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
using PortalTypes = compvec::PortalTupleTraits<ArrayTuple>;
using PortalTupleType = typename PortalTypes::PortalTuple;
using PortalConstTupleType = typename PortalTypes::PortalConstTuple;
using ArrayTuple = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
ArrayTuple Arrays;
bool Valid;
public:
using ValueType = typename compvec::GetValueType<ArrayTuple>::ValueType;
using PortalType = ArrayPortalCompositeVector<PortalTupleType>;
using PortalConstType = ArrayPortalCompositeVector<PortalConstTupleType>;
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
using PortalType = ArrayPortalCompositeVector<
typename vtkm::cont::ArrayHandle<T, StorageTags>::WritePortalType...>;
using PortalConstType =
ArrayPortalCompositeVector<typename vtkm::cont::ArrayHandle<T, StorageTags>::ReadPortalType...>;
VTKM_CONT
Storage()
@ -538,18 +389,6 @@ public:
{
}
VTKM_CONT
Storage(const ArrayTuple& arrays)
: Arrays(arrays)
, Valid(true)
{
using SizeValidator = compvec::ArraySizeValidator<ArrayTuple>;
if (!SizeValidator::Exec(this->Arrays, this->GetNumberOfValues()))
{
throw ErrorBadValue("All arrays must have the same number of values.");
}
}
template <typename... ArrayTypes>
VTKM_CONT Storage(const ArrayTypes&... arrays)
: Arrays(arrays...)
@ -566,42 +405,44 @@ public:
PortalType GetPortal()
{
VTKM_ASSERT(this->Valid);
return PortalType(PortalTypes::GetPortalTupleControl(this->Arrays));
return this->Arrays.Transform(compvec::WritePortal{});
}
void TypeCheck(int) const;
VTKM_CONT
PortalConstType GetPortalConst() const
{
VTKM_ASSERT(this->Valid);
return PortalConstType(PortalTypes::GetPortalConstTupleControl(this->Arrays));
this->Arrays.Transform(compvec::ReadPortal{});
return this->Arrays.Transform(compvec::ReadPortal{});
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(this->Valid);
return vtkmstd::get<0>(this->Arrays).GetNumberOfValues();
return vtkm::Get<0>(this->Arrays).GetNumberOfValues();
}
VTKM_CONT
void Allocate(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
ForEachArray::Allocate(this->Arrays, numValues);
this->Arrays.ForEach(compvec::Allocate{ numValues });
}
VTKM_CONT
void Shrink(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
ForEachArray::Shrink(this->Arrays, numValues);
this->Arrays.ForEach(compvec::Shrink{ numValues });
}
VTKM_CONT
void ReleaseResources()
{
VTKM_ASSERT(this->Valid);
ForEachArray::ReleaseResources(this->Arrays);
this->Arrays.ForEach(compvec::ReleaseResources{});
}
VTKM_CONT
@ -617,28 +458,25 @@ public:
VTKM_ASSERT(this->Valid);
return this->Arrays;
}
private:
ArrayTuple Arrays;
bool Valid;
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... Arrays, typename DeviceTag>
struct ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
StorageTagCompositeVector<vtkmstd::tuple<Arrays...>>,
DeviceTag>
: ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
typename CompositeVectorTraits<Arrays...>::StorageType,
DeviceTag>
// Special case for single component. Just defer to the original storage.
template <typename T, typename StorageTag>
class Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : public Storage<T, StorageTag>
{
using Superclass =
ArrayTransfer<typename compvec::GetValueType<vtkmstd::tuple<Arrays...>>::ValueType,
typename CompositeVectorTraits<Arrays...>::StorageType,
DeviceTag>;
using Superclass::Superclass;
using ArrayType = vtkm::cont::ArrayHandle<T, StorageTag>;
using TupleType = vtkm::Tuple<ArrayType>;
public:
Storage() = default;
Storage(const ArrayType& array)
: Storage<T, StorageTag>(array.GetStorage())
{
}
VTKM_CONT
const TupleType GetArrayTuple() const { return TupleType(ArrayType(this->GetStoragea())); }
};
VTKM_DEPRECATED_SUPPRESS_END
template <typename T, typename... StorageTags, typename DeviceTag>
class ArrayTransfer<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>,
@ -647,26 +485,27 @@ class ArrayTransfer<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(Storag
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceTag);
using ArrayTuple = vtkmstd::tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
using ArrayTuple = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
public:
using ValueType = typename compvec::GetValueType<ArrayTuple>::ValueType;
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
private:
using ForEachArray =
compvec::ArrayTupleForEach<0, vtkmstd::tuple_size<ArrayTuple>::value, ArrayTuple>;
using StorageTag = vtkm::cont::StorageTagCompositeVec<StorageTags...>;
using StorageType = internal::Storage<ValueType, StorageTag>;
using ControlTraits = compvec::PortalTupleTraits<ArrayTuple>;
using ExecutionTraits = typename ControlTraits::template ExecutionTypes<DeviceTag>;
StorageType* Storage;
public:
using PortalControl = ArrayPortalCompositeVector<typename ControlTraits::PortalTuple>;
using PortalConstControl = ArrayPortalCompositeVector<typename ControlTraits::PortalConstTuple>;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
using PortalExecution = ArrayPortalCompositeVector<typename ExecutionTraits::PortalTuple>;
using PortalExecution = ArrayPortalCompositeVector<
typename vtkm::cont::ArrayHandle<T,
StorageTags>::template ExecutionTypes<DeviceTag>::Portal...>;
using PortalConstExecution =
ArrayPortalCompositeVector<typename ExecutionTraits::PortalConstTuple>;
ArrayPortalCompositeVector<typename vtkm::cont::ArrayHandle<T, StorageTags>::
template ExecutionTypes<DeviceTag>::PortalConst...>;
VTKM_CONT
ArrayTransfer(StorageType* storage)
@ -680,22 +519,20 @@ public:
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) const
{
return PortalConstExecution(
ControlTraits::template PrepareForInput<DeviceTag>(this->GetArrayTuple(), token));
return this->GetArrayTuple().Transform(compvec::PrepareForInput<DeviceTag>{ token });
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
{
return PortalExecution(
ControlTraits::template PrepareForInPlace<DeviceTag>(this->GetArrayTuple(), token));
return this->GetArrayTuple().Transform(compvec::PrepareForInPlace<DeviceTag>{ token });
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id numValues, vtkm::cont::Token& token)
{
return PortalExecution(
ControlTraits::template PrepareForOutput<DeviceTag>(this->GetArrayTuple(), numValues, token));
return this->GetArrayTuple().Transform(
compvec::PrepareForOutput<DeviceTag>{ numValues, token });
}
VTKM_CONT
@ -707,17 +544,14 @@ public:
}
VTKM_CONT
void Shrink(vtkm::Id numValues) { ForEachArray::Shrink(this->GetArrayTuple(), numValues); }
void Shrink(vtkm::Id numValues) { this->GetArrayTuple().ForEach(compvec::Shrink{ numValues }); }
VTKM_CONT
void ReleaseResources() { ForEachArray::ReleaseResources(this->GetArrayTuple()); }
void ReleaseResources() { this->GetArrayTuple().ForEach(compvec::ReleaseResourcesExecution{}); }
VTKM_CONT
const ArrayTuple& GetArrayTuple() const { return this->Storage->GetArrayTuple(); }
ArrayTuple& GetArrayTuple() { return this->Storage->GetArrayTuple(); }
private:
StorageType* Storage;
};
} // namespace internal
@ -742,7 +576,7 @@ class ArrayHandleCompositeVector
{
private:
using Traits = internal::CompositeVectorTraits<ArrayTs...>;
using TupleType = vtkmstd::tuple<ArrayTs...>;
using TupleType = vtkm::Tuple<ArrayTs...>;
using StorageType = typename Traits::StorageType;
public:
@ -798,59 +632,12 @@ struct SerializableTypeString<
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
{
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... AHs>
struct SerializableTypeString<vtkm::cont::ArrayHandle<
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<vtkmstd::tuple<AHs...>>>>
: SerializableTypeString<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
};
VTKM_DEPRECATED_SUPPRESS_END
}
} // vtkm::cont
namespace mangled_diy_namespace
{
namespace internal
{
template <typename Functor, typename TupleType, typename... Args>
inline void TupleForEachImpl(TupleType&& t,
std::integral_constant<size_t, 0>,
Functor&& f,
Args&&... args)
{
f(vtkmstd::get<0>(t), std::forward<Args>(args)...);
}
template <typename Functor, typename TupleType, size_t Index, typename... Args>
inline void TupleForEachImpl(TupleType&& t,
std::integral_constant<size_t, Index>,
Functor&& f,
Args&&... args)
{
TupleForEachImpl(std::forward<TupleType>(t),
std::integral_constant<size_t, Index - 1>{},
std::forward<Functor>(f),
std::forward<Args>(args)...);
f(vtkmstd::get<Index>(t), std::forward<Args>(args)...);
}
template <typename Functor, typename TupleType, typename... Args>
inline void TupleForEach(TupleType&& t, Functor&& f, Args&&... args)
{
constexpr auto size = vtkmstd::tuple_size<typename std::decay<TupleType>::type>::value;
TupleForEachImpl(std::forward<TupleType>(t),
std::integral_constant<size_t, size - 1>{},
std::forward<Functor>(f),
std::forward<Args>(args)...);
}
} // internal
template <typename... AHs>
struct Serialization<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
@ -860,33 +647,47 @@ private:
struct SaveFunctor
{
template <typename AH>
void operator()(const AH& ah, BinaryBuffer& bb) const
BinaryBuffer& Buffer;
SaveFunctor(BinaryBuffer& bb)
: Buffer(bb)
{
vtkmdiy::save(bb, ah);
}
template <typename AH>
void operator()(const AH& ah) const
{
vtkmdiy::save(this->Buffer, ah);
}
};
struct LoadFunctor
{
template <typename AH>
void operator()(AH& ah, BinaryBuffer& bb) const
BinaryBuffer& Buffer;
LoadFunctor(BinaryBuffer& bb)
: Buffer(bb)
{
vtkmdiy::load(bb, ah);
}
template <typename AH>
void operator()(AH& ah) const
{
vtkmdiy::load(this->Buffer, ah);
}
};
static BaseType Create(const AHs&... arrays) { return Type(arrays...); }
public:
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
{
internal::TupleForEach(obj.GetStorage().GetArrayTuple(), SaveFunctor{}, bb);
obj.GetStorage().GetArrayTuple().ForEach(SaveFunctor{ bb });
}
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
{
vtkmstd::tuple<AHs...> arrayTuple;
internal::TupleForEach(arrayTuple, LoadFunctor{}, bb);
obj = BaseType(typename BaseType::StorageType(arrayTuple));
vtkm::Tuple<AHs...> tuple;
tuple.ForEach(LoadFunctor{ bb });
obj = tuple.Apply(Create);
}
};
@ -897,16 +698,6 @@ struct Serialization<
: Serialization<vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, STs>...>>
{
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename... AHs>
struct Serialization<vtkm::cont::ArrayHandle<
typename vtkm::cont::internal::compvec::GetValueType<vtkmstd::tuple<AHs...>>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<vtkmstd::tuple<AHs...>>>>
: Serialization<vtkm::cont::ArrayHandleCompositeVector<AHs...>>
{
};
VTKM_DEPRECATED_SUPPRESS_END
} // diy
/// @endcond SERIALIZATION

@ -15,29 +15,18 @@
#include <vtkm/cont/Storage.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/Tuple.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkm/internal/brigand.hpp>
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <vtkmstd/integer_sequence.h>
#include <type_traits>
#include <utility>
// Some compilers like brigand's integer sequences.
// Some compilers prefer tao's.
// Brigand seems to have more support, so we'll use that as default and fallback
// to tao when brigand fails. With C++14, we'll be able to just use the STL.
#if !defined(VTKM_CUDA_DEVICE_PASS) && \
(defined(VTKM_GCC) || \
(defined(__apple_build_version__) && (__apple_build_version__ >= 10000000)) || \
(defined(VTKM_CLANG) && (__clang_major__ >= 5)))
#define VTKM_USE_TAO_SEQ
#endif
namespace vtkm
{
namespace cont
@ -407,14 +396,10 @@ struct DecoratorStorageTraits
"ArrayHandleDecorator must be a list of ArrayHandle "
"types.");
using ArrayTupleType = vtkmstd::tuple<ArrayTs...>;
using ArrayTupleType = vtkm::Tuple<ArrayTs...>;
// size_t integral constants that index ArrayTs:
#ifndef VTKM_USE_TAO_SEQ
using IndexList = brigand::make_sequence<brigand::size_t<0>, sizeof...(ArrayTs)>;
#else // VTKM_USE_TAO_SEQ
using IndexList = tao::seq::make_index_sequence<sizeof...(ArrayTs)>;
#endif // VTKM_USE_TAO_SEQ
// size_t integral constants that index ArrayTs:
using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>;
// true_type/false_type depending on whether the decorator supports Allocate/Shrink:
using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
@ -532,186 +517,83 @@ struct DecoratorStorageTraits
}
#ifndef VTKM_USE_TAO_SEQ
// Portal construction methods. These actually create portals.
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues,
impl,
// More MSVC ICE avoidance while expanding the Indices parameter pack,
// which is a list of std::integral_constant<size_t, ...>:
//
// Indices::value : Works everywhere but MSVC2017, which crashes on it.
// Indices{} : Works on MSVC2017, but won't compile on MSVC2015.
// Indices{}.value : Works on both MSVC2015 and MSVC2017.
//
// Don't touch the following line unless you really, really have to.
WritePortal(vtkmstd::get<Indices{}.value>(arrays))...);
numValues, impl, WritePortal(vtkm::Get<Indices>(arrays))...);
}
template <template <typename...> class List, typename... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
template <std::size_t... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(
const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
ReadPortal(vtkmstd::get<Indices{}.value>(arrays))...);
numValues, impl, ReadPortal(vtkm::Get<Indices>(arrays))...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev,
vtkm::cont::Token& token)
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(
const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalInput(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev,
vtkm::cont::Token& token)
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(
const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInPlace(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalInPlace(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
template <typename Device, std::size_t... Indices>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
vtkmstd::index_sequence<Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalOutput(vtkmstd::get<Indices{}.value>(arrays), dev, token)...);
numValues, impl, GetPortalOutput(vtkm::Get<Indices>(arrays), dev, token)...);
}
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
CallAllocate(IsAllocatable{}, impl, numValues, vtkm::Get<Indices>(arrays)...);
}
template <template <typename...> class List, typename... Indices>
template <std::size_t... Indices>
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
vtkmstd::index_sequence<Indices...>)
{
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices{}.value>(arrays)...);
CallShrink(IsShrinkable{}, impl, numValues, vtkm::Get<Indices>(arrays)...);
}
#else // VTKM_USE_TAO_SEQ
// Portal construction methods. These actually create portals.
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues, impl, WritePortal(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues, impl, ReadPortal(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues, impl, GetPortalInput(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalInPlace(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev,
vtkm::cont::Token& token)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalOutput(vtkmstd::get<Indices>(arrays), dev, token)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
CallAllocate(IsAllocatable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static void ShrinkSourceArrays(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
CallShrink(IsShrinkable{}, impl, numValues, vtkmstd::get<Indices>(arrays)...);
}
#endif // VTKM_USE_TAO_SEQ
};
} // end namespace decor
@ -1030,7 +912,7 @@ public:
ArrayHandleDecorator(vtkm::Id numValues,
const typename std::decay<DecoratorImplT>::type& impl,
const typename std::decay<ArrayTs>::type&... arrays)
: Superclass{ StorageType{ impl, vtkmstd::make_tuple(arrays...), numValues } }
: Superclass{ StorageType{ impl, vtkm::MakeTuple(arrays...), numValues } }
{
}
};

@ -17,7 +17,7 @@
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <vtkmstd/integer_sequence.h>
#include <array>
#include <limits>
@ -70,7 +70,7 @@ public:
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex) const
{
return this->Get(valueIndex, tao::seq::make_index_sequence<NUM_COMPONENTS>());
return this->Get(valueIndex, vtkmstd::make_index_sequence<NUM_COMPONENTS>());
}
template <typename SPT = SourcePortalType,
@ -78,7 +78,7 @@ public:
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex, const ValueType& value) const
{
this->Set(valueIndex, value, tao::seq::make_index_sequence<NUM_COMPONENTS>());
this->Set(valueIndex, value, vtkmstd::make_index_sequence<NUM_COMPONENTS>());
}
private:
@ -89,7 +89,7 @@ private:
}
template <std::size_t... I>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, tao::seq::index_sequence<I...>) const
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, vtkmstd::index_sequence<I...>) const
{
return ValueType{ this->GetComponent<I>(valueIndex)... };
}
@ -105,7 +105,7 @@ private:
template <std::size_t... I>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex,
const ValueType& value,
tao::seq::index_sequence<I...>) const
vtkmstd::index_sequence<I...>) const
{
// Is there a better way to unpack an expression and execute them with no other side effects?
(void)std::initializer_list<bool>{ this->SetComponent<I>(valueIndex, value)... };

@ -15,30 +15,7 @@
#include <vtkm/internal/ArrayPortalHelpers.h>
namespace vtkmstd
{
/// Implementation of std::void_t (C++17):
/// Allows for specialization of class templates based on members of template
/// parameters.
#if defined(VTKM_GCC) && (__GNUC__ < 5)
// Due to a defect in the wording (CWG 1558) unused parameters in alias templates
// were not guaranteed to ensure SFINAE, and therefore would consider everything
// to match the 'true' side. For VTK-m the only known compiler that implemented
// this defect is GCC < 5.
template <class... T>
struct void_pack
{
using type = void;
};
template <class... T>
using void_t = typename void_pack<T...>::type;
#else
template <typename...>
using void_t = void;
#endif
} // end namespace vtkmstd
#include <vtkmstd/void_t.h>
namespace vtkm
{

@ -217,7 +217,7 @@ endif()
target_link_libraries(vtkm_cont PUBLIC vtkm_compiler_flags ${backends})
target_link_libraries(vtkm_cont PUBLIC Threads::Threads)
target_link_libraries(vtkm_cont PUBLIC vtkm_taotuple vtkm_optionparser vtkm_diy vtkm_lcl)
target_link_libraries(vtkm_cont PUBLIC vtkm_optionparser vtkm_diy vtkm_lcl)
if(TARGET vtkm_loguru)
target_link_libraries(vtkm_cont PRIVATE vtkm_loguru)
endif()

@ -69,7 +69,7 @@ struct Invoker
typename std::enable_if<detail::scatter_or_mask<T>::value, int>::type* = nullptr>
inline void operator()(Worklet&& worklet, T&& scatterOrMask, Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet, scatterOrMask);
@ -94,7 +94,7 @@ struct Invoker
U&& scatterOrMaskB,
Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet, scatterOrMaskA, scatterOrMaskB);
@ -112,7 +112,7 @@ struct Invoker
typename std::enable_if<!detail::scatter_or_mask<T>::value, int>::type* = nullptr>
inline void operator()(Worklet&& worklet, T&& t, Args&&... args) const
{
using WorkletType = worklet::internal::remove_cvref<Worklet>;
using WorkletType = vtkm::internal::remove_cvref<Worklet>;
using DispatcherType = typename WorkletType::template Dispatcher<WorkletType>;
DispatcherType dispatcher(worklet);

@ -56,6 +56,7 @@ set(headers
ConfigureFor32.h
ConfigureFor64.h
ConnectivityStructuredInternals.h
DecayHelpers.h
ExportMacros.h
FunctionInterface.h
FunctionInterfaceDetailPost.h

@ -14,8 +14,6 @@
namespace vtkm
{
namespace worklet
{
namespace internal
{
@ -25,6 +23,5 @@ using remove_pointer_and_decay = typename std::remove_pointer<typename std::deca
template <typename T>
using remove_cvref = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
}
}
}
} // namespace vtkm::internal
#endif

@ -15,67 +15,8 @@
#include <vtkm/Deprecated.h>
#include <vtkm/List.h>
#if defined(VTKM_USING_GLIBCXX_4)
// It would make sense to put this in its own header file, but it is hard to imagine needing
// aligned_union anywhere else.
#include <algorithm>
namespace vtkmstd
{
template <std::size_t... Xs>
struct max_size;
template <std::size_t X>
struct max_size<X>
{
static constexpr std::size_t value = X;
};
template <std::size_t X0, std::size_t... Xs>
struct max_size<X0, Xs...>
{
static constexpr std::size_t other_value = max_size<Xs...>::value;
static constexpr std::size_t value = (other_value > X0) ? other_value : X0;
};
// This is to get around an apparent bug in GCC 4.8 where alianas(x) does not
// seem to work when x is a constexpr. See
// https://stackoverflow.com/questions/29879609/g-complains-constexpr-function-is-not-a-constant-expression
template <std::size_t Alignment, std::size_t Size>
struct aligned_data_block
{
alignas(Alignment) char _s[Size];
};
template <std::size_t Len, class... Types>
struct aligned_union
{
static constexpr std::size_t alignment_value = vtkmstd::max_size<alignof(Types)...>::value;
using type =
vtkmstd::aligned_data_block<alignment_value, vtkmstd::max_size<Len, sizeof(Types)...>::value>;
};
// GCC 4.8 and 4.9 standard library does not support std::is_trivially_copyable.
// There is no relyable way to get this information (since it has to come special from
// the compiler). For our purposes, we will report as nothing being trivially copyable,
// which causes us to call the constructors with everything. This should be fine unless
// some other part of the compiler is trying to check for trivial copies (perhaps nvcc
// on top of GCC 4.8).
template <typename>
struct is_trivially_copyable : std::false_type
{
};
} // namespace vtkmstd
#else // NOT VTKM_USING_GLIBCXX_4
namespace vtkmstd
{
using std::aligned_union;
using std::is_trivially_copyable;
} // namespace vtkmstd
#endif
#include <vtkmstd/aligned_union.h>
#include <vtkmstd/is_trivially_copyable.h>
namespace vtkm
{

@ -37,6 +37,7 @@ set(unit_tests
UnitTestRange.cxx
UnitTestTesting.cxx
UnitTestTransform3D.cxx
UnitTestTuple.cxx
UnitTestTypeList.cxx
UnitTestTypeListTag.cxx
UnitTestTypes.cxx

@ -0,0 +1,383 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/Tuple.h>
#include <vtkmstd/integer_sequence.h>
#include <vtkm/testing/Testing.h>
namespace
{
// Do some compile-time testing of vtkmstd::integer_sequence. This is only tangentially
// related to Tuple, but the two are often used together.
template <vtkm::IdComponent... Ns>
using SequenceId = vtkmstd::integer_sequence<vtkm::IdComponent, Ns...>;
template <vtkm::IdComponent N>
using MakeSequenceId = vtkmstd::make_integer_sequence<vtkm::IdComponent, N>;
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<0>, SequenceId<>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<1>, SequenceId<0>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<2>, SequenceId<0, 1>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<3>, SequenceId<0, 1, 2>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<5>, SequenceId<0, 1, 2, 3, 4>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<8>, SequenceId<0, 1, 2, 3, 4, 5, 6, 7>>::value));
VTKM_STATIC_ASSERT(
(std::is_same<MakeSequenceId<13>, SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>>::value));
VTKM_STATIC_ASSERT(
(std::is_same<
MakeSequenceId<21>,
SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<34>,
SequenceId<0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33>>::value));
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<89>,
SequenceId<0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88>>::value));
template <vtkm::IdComponent Index>
struct TypePlaceholder
{
vtkm::Id X;
TypePlaceholder(vtkm::Id x)
: X(x)
{
}
};
void Check2(TypePlaceholder<0> a0, TypePlaceholder<1> a1)
{
VTKM_TEST_ASSERT(a0.X == TestValue(0, vtkm::Id{}));
VTKM_TEST_ASSERT(a1.X == TestValue(1, vtkm::Id{}));
}
void Check22(TypePlaceholder<0> a0,
TypePlaceholder<1> a1,
TypePlaceholder<2> a2,
TypePlaceholder<3> a3,
TypePlaceholder<4> a4,
TypePlaceholder<5> a5,
TypePlaceholder<6> a6,
TypePlaceholder<7> a7,
TypePlaceholder<8> a8,
TypePlaceholder<9> a9,
TypePlaceholder<10> a10,
TypePlaceholder<11> a11,
TypePlaceholder<12> a12,
TypePlaceholder<13> a13,
TypePlaceholder<14> a14,
TypePlaceholder<15> a15,
TypePlaceholder<16> a16,
TypePlaceholder<17> a17,
TypePlaceholder<18> a18,
TypePlaceholder<19> a19,
TypePlaceholder<20> a20,
TypePlaceholder<21> a21)
{
VTKM_TEST_ASSERT(a0.X == TestValue(0, vtkm::Id{}));
VTKM_TEST_ASSERT(a1.X == TestValue(1, vtkm::Id{}));
VTKM_TEST_ASSERT(a2.X == TestValue(2, vtkm::Id{}));
VTKM_TEST_ASSERT(a3.X == TestValue(3, vtkm::Id{}));
VTKM_TEST_ASSERT(a4.X == TestValue(4, vtkm::Id{}));
VTKM_TEST_ASSERT(a5.X == TestValue(5, vtkm::Id{}));
VTKM_TEST_ASSERT(a6.X == TestValue(6, vtkm::Id{}));
VTKM_TEST_ASSERT(a7.X == TestValue(7, vtkm::Id{}));
VTKM_TEST_ASSERT(a8.X == TestValue(8, vtkm::Id{}));
VTKM_TEST_ASSERT(a9.X == TestValue(9, vtkm::Id{}));
VTKM_TEST_ASSERT(a10.X == TestValue(10, vtkm::Id{}));
VTKM_TEST_ASSERT(a11.X == TestValue(11, vtkm::Id{}));
VTKM_TEST_ASSERT(a12.X == TestValue(12, vtkm::Id{}));
VTKM_TEST_ASSERT(a13.X == TestValue(13, vtkm::Id{}));
VTKM_TEST_ASSERT(a14.X == TestValue(14, vtkm::Id{}));
VTKM_TEST_ASSERT(a15.X == TestValue(15, vtkm::Id{}));
VTKM_TEST_ASSERT(a16.X == TestValue(16, vtkm::Id{}));
VTKM_TEST_ASSERT(a17.X == TestValue(17, vtkm::Id{}));
VTKM_TEST_ASSERT(a18.X == TestValue(18, vtkm::Id{}));
VTKM_TEST_ASSERT(a19.X == TestValue(19, vtkm::Id{}));
VTKM_TEST_ASSERT(a20.X == TestValue(20, vtkm::Id{}));
VTKM_TEST_ASSERT(a21.X == TestValue(21, vtkm::Id{}));
}
struct CheckReturn
{
template <typename Function, typename... Ts>
vtkm::Id operator()(Function f, Ts... args)
{
f(args...);
return vtkm::Id(sizeof...(Ts));
}
};
struct CheckValues
{
vtkm::IdComponent NumChecked = 0;
template <vtkm::IdComponent Index>
void operator()(TypePlaceholder<Index> x)
{
VTKM_TEST_ASSERT(x.X == TestValue(Index, vtkm::Id{}));
this->NumChecked++;
}
};
struct TransformValues
{
vtkm::Id AddValue;
TransformValues(vtkm::Id addValue)
: AddValue(addValue)
{
}
template <vtkm::IdComponent Index>
vtkm::Id operator()(TypePlaceholder<Index> x) const
{
return x.X + this->AddValue;
}
};
void TestTuple2()
{
using TupleType = vtkm::Tuple<TypePlaceholder<0>, TypePlaceholder<1>>;
VTKM_STATIC_ASSERT(vtkm::TupleSize<TupleType>::value == 2);
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<0>, vtkm::TupleElement<0, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<1>, vtkm::TupleElement<1, TupleType>>::value));
TupleType tuple(TestValue(0, vtkm::Id()), TestValue(1, vtkm::Id()));
tuple.Apply(Check2);
vtkm::Id result = tuple.Apply(CheckReturn{}, Check2);
VTKM_TEST_ASSERT(result == 2);
CheckValues checkFunctor;
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 0);
tuple.ForEach(checkFunctor);
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 2);
auto transformedTuple = tuple.Transform(TransformValues{ 10 });
using TransformedTupleType = decltype(transformedTuple);
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<0, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<1, TransformedTupleType>, vtkm::Id>::value));
VTKM_TEST_ASSERT(vtkm::Get<0>(transformedTuple) == TestValue(0, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<1>(transformedTuple) == TestValue(1, vtkm::Id{}) + 10);
}
void TestTuple22()
{
using TupleType = vtkm::Tuple<TypePlaceholder<0>,
TypePlaceholder<1>,
TypePlaceholder<2>,
TypePlaceholder<3>,
TypePlaceholder<4>,
TypePlaceholder<5>,
TypePlaceholder<6>,
TypePlaceholder<7>,
TypePlaceholder<8>,
TypePlaceholder<9>,
TypePlaceholder<10>,
TypePlaceholder<11>,
TypePlaceholder<12>,
TypePlaceholder<13>,
TypePlaceholder<14>,
TypePlaceholder<15>,
TypePlaceholder<16>,
TypePlaceholder<17>,
TypePlaceholder<18>,
TypePlaceholder<19>,
TypePlaceholder<20>,
TypePlaceholder<21>>;
VTKM_STATIC_ASSERT(vtkm::TupleSize<TupleType>::value == 22);
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<0>, vtkm::TupleElement<0, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<1>, vtkm::TupleElement<1, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<20>, vtkm::TupleElement<20, TupleType>>::value));
VTKM_STATIC_ASSERT((std::is_same<TypePlaceholder<21>, vtkm::TupleElement<21, TupleType>>::value));
TupleType tuple(TestValue(0, vtkm::Id()),
TestValue(1, vtkm::Id()),
TestValue(2, vtkm::Id()),
TestValue(3, vtkm::Id()),
TestValue(4, vtkm::Id()),
TestValue(5, vtkm::Id()),
TestValue(6, vtkm::Id()),
TestValue(7, vtkm::Id()),
TestValue(8, vtkm::Id()),
TestValue(9, vtkm::Id()),
TestValue(10, vtkm::Id()),
TestValue(11, vtkm::Id()),
TestValue(12, vtkm::Id()),
TestValue(13, vtkm::Id()),
TestValue(14, vtkm::Id()),
TestValue(15, vtkm::Id()),
TestValue(16, vtkm::Id()),
TestValue(17, vtkm::Id()),
TestValue(18, vtkm::Id()),
TestValue(19, vtkm::Id()),
TestValue(20, vtkm::Id()),
TestValue(21, vtkm::Id()));
tuple.Apply(Check22);
vtkm::Id result = tuple.Apply(CheckReturn{}, Check22);
VTKM_TEST_ASSERT(result == 22);
CheckValues checkFunctor;
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 0);
tuple.ForEach(checkFunctor);
VTKM_TEST_ASSERT(checkFunctor.NumChecked == 22);
auto transformedTuple = tuple.Transform(TransformValues{ 10 });
using TransformedTupleType = decltype(transformedTuple);
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<0, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<1, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<20, TransformedTupleType>, vtkm::Id>::value));
VTKM_STATIC_ASSERT((std::is_same<vtkm::TupleElement<21, TransformedTupleType>, vtkm::Id>::value));
VTKM_TEST_ASSERT(vtkm::Get<0>(transformedTuple) == TestValue(0, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<1>(transformedTuple) == TestValue(1, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<20>(transformedTuple) == TestValue(20, vtkm::Id{}) + 10);
VTKM_TEST_ASSERT(vtkm::Get<21>(transformedTuple) == TestValue(21, vtkm::Id{}) + 10);
}
void TestTuple()
{
TestTuple2();
TestTuple22();
}
} // anonymous namespace
int UnitTestTuple(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(TestTuple, argc, argv);
}

@ -1,28 +0,0 @@
##============================================================================
## 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.
##============================================================================
add_library(vtkm_taotuple INTERFACE)
vtkm_get_kit_name(kit_name kit_dir)
# taotuple needs C++11
target_compile_features(vtkm_taotuple INTERFACE cxx_std_11)
target_include_directories(vtkm_taotuple INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${VTKm_INSTALL_INCLUDE_DIR}/vtkm/thirdparty/taotuple>)
install(TARGETS vtkm_taotuple
EXPORT ${VTKm_EXPORT_NAME})
## Install headers
if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
install(DIRECTORY vtkmtaotuple
DESTINATION ${VTKm_INSTALL_INCLUDE_DIR}/${kit_dir}/)
endif()

@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -e
set -x
shopt -s dotglob
readonly name="taotuple"
readonly ownership="TaoCpp Tuple Upstream <kwrobot@kitware.com>"
readonly subtree="vtkm/thirdparty/$name/vtkm$name"
readonly repo="https://gitlab.kitware.com/third-party/$name.git"
readonly tag="for/vtk-m"
readonly paths="
include
LICENSE
README.md
"
extract_source () {
git_archive
}
. "${BASH_SOURCE%/*}/../update-common.sh"

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015-2018 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.

@ -1,43 +0,0 @@
# The Art of C++ / Tuple
[![Release](https://img.shields.io/github/release/taocpp/tuple.svg)](https://github.com/taocpp/tuple/releases/latest)
[![TravisCI](https://travis-ci.org/taocpp/tuple.svg)](https://travis-ci.org/taocpp/tuple)
[![AppVeyor](https://ci.appveyor.com/api/projects/status/9opt30ae579kw19b/branch/master?svg=true)](https://ci.appveyor.com/project/taocpp/tuple)
[The Art of C++](https://taocpp.github.io/) / 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-2018 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.

@ -1,498 +0,0 @@
//============================================================================
// 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
// Ignore "calling a __host__ function from a __host__ _device__ function is not allowed" warnings
#ifndef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#ifdef __CUDACC__
#if __CUDAVER__ >= 75000
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma nv_exec_check_disable
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN #pragma hd_warning_disable
#endif
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#endif
#endif
namespace simple_tuple
{
namespace detail
{
template <std::size_t Index, typename Head>
class tuple_leaf
{
protected:
Head Value;
public:
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf()
: Value()
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(const Head& value)
: Value(value)
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(const tuple_leaf& o)
: Value(o.Value)
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAOCPP_ANNOTATION constexpr tuple_leaf(tuple_leaf&& o)
: Value(std::move(o.Value))
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
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;
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
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:
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))
{
}
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:
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)...)
{
}
constexpr tuple(const tuple&) = default;
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

@ -1,58 +0,0 @@
//============================================================================
// 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 defined(_MSC_VER) && _MSC_VER == 1900
#define TAOCPP_USE_SIMPLE_TUPLE
// There is a bug in apple clang 9.0 that prevents tao-tuple from compiling:
#elif defined(__apple_build_version__) && defined(__clang__) && __clang_major__ == 9 && \
clang_minor == 0
#define TAOCPP_USE_SIMPLE_TUPLE
#endif
#ifdef TAOCPP_USE_SIMPLE_TUPLE
#include "SimpleTuple.h"
#else
#include "tao/tuple/tuple.hpp"
#endif
namespace vtkmstd
{
#ifdef TAOCPP_USE_SIMPLE_TUPLE
using simple_tuple::get;
using simple_tuple::make_tuple;
using simple_tuple::tuple;
using simple_tuple::tuple_element;
using simple_tuple::tuple_size;
#else
using tao::get;
using tao::make_tuple;
using tao::tuple;
using tao::tuple_element;
using tao::tuple_size;
#endif
} // end namespace vtkmstd
#endif // Tuple_h

@ -1,64 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_AT_INDEX_HPP
#define TAO_SEQ_AT_INDEX_HPP
#include <cstddef>
#include "make_integer_sequence.hpp"
namespace tao
{
namespace seq
{
// based on http://talesofcpp.fusionfenix.com/post-22/true-story-efficient-packing
namespace impl
{
template< std::size_t, typename T >
struct indexed
{
using type = T;
};
template< typename, typename... Ts >
struct indexer;
template< std::size_t... Is, typename... Ts >
struct indexer< index_sequence< Is... >, Ts... >
: indexed< Is, Ts >...
{
};
template< std::size_t I, typename T >
indexed< I, T > select( const indexed< I, T >& );
} // namespace impl
template< std::size_t I, typename... Ts >
using at_index = decltype( impl::select< I >( impl::indexer< index_sequence_for< Ts... >, Ts... >() ) );
#ifndef _MSC_VER
template< std::size_t I, typename... Ts >
using at_index_t = typename at_index< I, Ts... >::type;
#else
namespace impl
{
template< typename T >
struct get_type
{
using type = typename T::type;
};
} // namespace impl
template< std::size_t I, typename... Ts >
using at_index_t = typename impl::get_type< at_index< I, Ts... > >::type;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,33 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_CONFIG_HPP
#define TAO_SEQ_CONFIG_HPP
#include <utility>
#ifndef TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#if defined( __cpp_lib_integer_sequence )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#elif defined( _MSC_VER )
#define TAO_SEQ_USE_STD_INTEGER_SEQUENCE
#endif
#endif
#ifndef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#if defined( _GLIBCXX_RELEASE ) && ( _GLIBCXX_RELEASE >= 8 ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#elif defined( _LIBCPP_VERSION ) && ( __cplusplus >= 201402L )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#elif defined( _MSC_VER ) && ( _MSC_FULL_VER >= 190023918 )
#define TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
#endif
#endif
#if defined( __cpp_fold_expressions ) && ( !defined( __GNUC__ ) || ( __GNUC__ >= 8 ) )
#define TAO_SEQ_FOLD_EXPRESSIONS
#endif
#endif

@ -1,48 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_EXCLUSIVE_SCAN_HPP
#define TAO_SEQ_EXCLUSIVE_SCAN_HPP
#include <utility>
#include "make_integer_sequence.hpp"
#include "partial_sum.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
template< typename S, typename = make_index_sequence< S::size() > >
struct exclusive_scan;
template< typename S, std::size_t... Is >
struct exclusive_scan< S, index_sequence< Is... > >
{
using type = integer_sequence< typename S::value_type, partial_sum< Is, S >::value... >;
};
} // namespace impl
template< typename T, T... Ns >
struct exclusive_scan
: impl::exclusive_scan< integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
struct exclusive_scan< integer_sequence< T, Ns... > >
: impl::exclusive_scan< integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
using exclusive_scan_t = typename exclusive_scan< T, Ns... >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,36 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_INCLUSIVE_SCAN_HPP
#define TAO_SEQ_INCLUSIVE_SCAN_HPP
#include <utility>
#include "exclusive_scan.hpp"
#include "integer_sequence.hpp"
#include "plus.hpp"
namespace tao
{
namespace seq
{
template< typename T, T... Ns >
struct inclusive_scan
: plus< exclusive_scan_t< T, Ns... >, integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
struct inclusive_scan< integer_sequence< T, Ns... > >
: plus< exclusive_scan_t< integer_sequence< T, Ns... > >, integer_sequence< T, Ns... > >
{
};
template< typename T, T... Ns >
using inclusive_scan_t = typename inclusive_scan< T, Ns... >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,44 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_INTEGER_SEQUENCE_HPP
#define TAO_SEQ_INTEGER_SEQUENCE_HPP
#include <cstddef>
#include <utility>
#include "config.hpp"
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_USE_STD_INTEGER_SEQUENCE
using std::index_sequence;
using std::integer_sequence;
#else
template< typename T, T... Ns >
struct integer_sequence
{
using value_type = T;
static constexpr std::size_t size() noexcept
{
return sizeof...( Ns );
}
};
template< std::size_t... Ns >
using index_sequence = integer_sequence< std::size_t, Ns... >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,36 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_IS_ALL_HPP
#define TAO_SEQ_IS_ALL_HPP
#include "config.hpp"
#ifndef TAO_SEQ_FOLD_EXPRESSIONS
#include "integer_sequence.hpp"
#endif
#include <type_traits>
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
template< bool... Bs >
using is_all = std::integral_constant< bool, ( Bs && ... ) >;
#else
template< bool... Bs >
using is_all = std::integral_constant< bool, std::is_same< integer_sequence< bool, true, Bs... >, integer_sequence< bool, Bs..., true > >::value >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,90 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP
#define TAO_SEQ_MAKE_INTEGER_SEQUENCE_HPP
#include <cstddef>
#include <type_traits>
#include <utility>
#include "config.hpp"
#include "integer_sequence.hpp"
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_USE_STD_MAKE_INTEGER_SEQUENCE
using std::index_sequence_for;
using std::make_index_sequence;
using std::make_integer_sequence;
#else
namespace impl
{
// we have four instantiations of generate_sequence<>, independent of T or N.
// V is the current bit, E is the end marker - if true, this is the last step.
template< bool V, bool E >
struct generate_sequence;
// last step: generate final integer sequence
template<>
struct generate_sequence< false, true >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = integer_sequence< T, Ns... >;
};
template<>
struct generate_sequence< true, true >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = integer_sequence< T, Ns..., S >;
};
// intermediate step: double existing values, append one more if V is set.
template<>
struct generate_sequence< false, false >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S, Ns..., ( Ns + S )... >;
};
template<>
struct generate_sequence< true, false >
{
template< typename T, T M, T N, std::size_t S, T... Ns >
using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S + 1, Ns..., ( Ns + S )..., 2 * S >;
};
// the final sequence per T/N should be memoized, it will probably be used multiple times.
// also checks the limit and starts the above generator properly.
template< typename T, T N >
struct memoize_sequence
{
static_assert( N < T( 1 << 20 ), "N too large" );
using type = typename generate_sequence< false, false >::template f< T, ( N < T( 1 << 1 ) ) ? T( 1 << 1 ) : ( N < T( 1 << 2 ) ) ? T( 1 << 2 ) : ( N < T( 1 << 3 ) ) ? T( 1 << 3 ) : ( N < T( 1 << 4 ) ) ? T( 1 << 4 ) : ( N < T( 1 << 5 ) ) ? T( 1 << 5 ) : ( N < T( 1 << 6 ) ) ? T( 1 << 6 ) : ( N < T( 1 << 7 ) ) ? T( 1 << 7 ) : ( N < T( 1 << 8 ) ) ? T( 1 << 8 ) : ( N < T( 1 << 9 ) ) ? T( 1 << 9 ) : ( N < T( 1 << 10 ) ) ? T( 1 << 10 ) : T( 1 << 20 ), N, 0 >;
};
} // namespace impl
template< typename T, T N >
using make_integer_sequence = typename impl::memoize_sequence< T, N >::type;
template< std::size_t N >
using make_index_sequence = make_integer_sequence< std::size_t, N >;
template< typename... Ts >
using index_sequence_for = make_index_sequence< sizeof...( Ts ) >;
#endif
} // namespace seq
} // namespace tao
#endif

@ -1,33 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MAP_HPP
#define TAO_SEQ_MAP_HPP
#include <cstddef>
#include <utility>
#include "integer_sequence.hpp"
#include "select.hpp"
namespace tao
{
namespace seq
{
template< typename, typename >
struct map;
template< std::size_t... Ns, typename M >
struct map< index_sequence< Ns... >, M >
{
using type = integer_sequence< typename M::value_type, select< Ns, M >::value... >;
};
template< typename S, typename M >
using map_t = typename map< S, M >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,35 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_MINUS_HPP
#define TAO_SEQ_MINUS_HPP
#include <type_traits>
#include "zip.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
struct minus
{
template< typename T, T A, T B >
using apply = std::integral_constant< T, A - B >;
};
} // namespace impl
template< typename A, typename B >
using minus = zip< impl::minus, A, B >;
template< typename A, typename B >
using minus_t = typename minus< A, B >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,47 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_PARTIAL_SUM_HPP
#define TAO_SEQ_PARTIAL_SUM_HPP
#include <cstddef>
#include <utility>
#include "make_integer_sequence.hpp"
#include "sum.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
template< std::size_t, typename S, typename = make_index_sequence< S::size() > >
struct partial_sum;
template< std::size_t I, typename T, T... Ns, std::size_t... Is >
struct partial_sum< I, integer_sequence< T, Ns... >, index_sequence< Is... > >
: seq::sum< T, ( ( Is < I ) ? Ns : 0 )... >
{
static_assert( I <= sizeof...( Is ), "tao::seq::partial_sum<I, S>: I is out of range" );
};
} // namespace impl
template< std::size_t I, typename T, T... Ns >
struct partial_sum
: impl::partial_sum< I, integer_sequence< T, Ns... > >
{
};
template< std::size_t I, typename T, T... Ns >
struct partial_sum< I, integer_sequence< T, Ns... > >
: impl::partial_sum< I, integer_sequence< T, Ns... > >
{
};
} // namespace seq
} // namespace tao
#endif

@ -1,35 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_PLUS_HPP
#define TAO_SEQ_PLUS_HPP
#include <type_traits>
#include "zip.hpp"
namespace tao
{
namespace seq
{
namespace impl
{
struct plus
{
template< typename T, T A, T B >
using apply = std::integral_constant< T, A + B >;
};
} // namespace impl
template< typename A, typename B >
using plus = zip< impl::plus, A, B >;
template< typename A, typename B >
using plus_t = typename plus< A, B >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,33 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_SELECT_HPP
#define TAO_SEQ_SELECT_HPP
#include <cstddef>
#include <utility>
#include "at_index.hpp"
#include "integer_sequence.hpp"
namespace tao
{
namespace seq
{
template< std::size_t I, typename T, T... Ns >
struct select
: at_index_t< I, std::integral_constant< T, Ns >... >
{
};
template< std::size_t I, typename T, T... Ns >
struct select< I, integer_sequence< T, Ns... > >
: select< I, T, Ns... >
{
};
} // namespace seq
} // namespace tao
#endif

@ -1,87 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_SUM_HPP
#define TAO_SEQ_SUM_HPP
#include <type_traits>
#include <utility>
#include "config.hpp"
#include "integer_sequence.hpp"
#ifndef TAO_SEQ_FOLD_EXPRESSIONS
#include "make_integer_sequence.hpp"
#include <cstddef>
#endif
namespace tao
{
namespace seq
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
template< typename T, T... Ns >
struct sum
: std::integral_constant< T, ( Ns + ... + T( 0 ) ) >
{
};
#else
namespace impl
{
template< std::size_t, std::size_t N >
struct chars
{
char dummy[ N + 1 ];
};
template< typename, std::size_t... >
struct collector;
template< std::size_t... Is, std::size_t... Ns >
struct collector< index_sequence< Is... >, Ns... >
: chars< Is, Ns >...
{
};
template< bool, std::size_t N, typename T, T... Ns >
struct sum;
template< std::size_t N, typename T, T... Ns >
struct sum< true, N, T, Ns... >
{
using type = std::integral_constant< T, T( sizeof( collector< make_index_sequence< N >, Ns... > ) - N ) >;
};
template< bool, std::size_t N, typename T, T... Ns >
struct sum
{
using positive = typename sum< true, N, T, ( ( Ns > 0 ) ? Ns : 0 )... >::type;
using negative = typename sum< true, N, T, ( ( Ns < 0 ) ? -Ns : 0 )... >::type;
using type = std::integral_constant< T, positive::value - negative::value >;
};
} // namespace impl
template< typename T, T... Ns >
struct sum
: impl::sum< std::is_unsigned< T >::value, sizeof...( Ns ) + 1, T, Ns..., 0 >::type
{
};
#endif
template< typename T, T... Ns >
struct sum< integer_sequence< T, Ns... > >
: sum< T, Ns... >
{
};
} // namespace seq
} // namespace tao
#endif

@ -1,60 +0,0 @@
// The Art of C++ / Sequences
// Copyright (c) 2015 Daniel Frey
#ifndef TAOCPP_SEQUENCES_INCLUDE_TYPE_BY_INDEX_HPP
#define TAOCPP_SEQUENCES_INCLUDE_TYPE_BY_INDEX_HPP
#include <cstddef>
#include <type_traits>
#include "make_integer_sequence.hpp"
namespace tao
{
namespace seq
{
// based on http://stackoverflow.com/questions/18942322
namespace impl
{
template< std::size_t >
struct any
{
any( ... );
};
template< typename >
struct wrapper;
template< typename >
struct unwrap;
template< typename T >
struct unwrap< wrapper< T > >
{
using type = T;
};
template< typename >
struct get_nth;
template< std::size_t... Is >
struct get_nth< index_sequence< Is... > >
{
template< typename T >
static T deduce( any< Is & 0 >..., T*, ... );
};
}
template< std::size_t I, typename... Ts >
struct type_by_index
{
using type = typename impl::unwrap< decltype( impl::get_nth< make_index_sequence< I > >::deduce( std::declval< impl::wrapper< Ts >* >()... ) ) >::type;
};
template< std::size_t I, typename... Ts >
using type_by_index_t = typename type_by_index< I, Ts... >::type;
}
}
#endif // TAOCPP_SEQUENCES_INCLUDE_TYPE_BY_INDEX_HPP

@ -1,32 +0,0 @@
// Copyright (c) 2015-2018 Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/sequences/
#ifndef TAO_SEQ_ZIP_HPP
#define TAO_SEQ_ZIP_HPP
#include <type_traits>
#include "integer_sequence.hpp"
namespace tao
{
namespace seq
{
template< typename, typename, typename >
struct zip;
template< typename OP, typename TA, TA... As, typename TB, TB... Bs >
struct zip< OP, integer_sequence< TA, As... >, integer_sequence< TB, Bs... > >
{
using CT = typename std::common_type< TA, TB >::type;
using type = integer_sequence< CT, OP::template apply< CT, As, Bs >::value... >;
};
template< typename OP, typename A, typename B >
using zip_t = typename zip< OP, A, B >::type;
} // namespace seq
} // namespace tao
#endif

@ -1,957 +0,0 @@
// The Art of C++ / Tuple
// Copyright (c) 2015-2018 Daniel Frey
#ifndef TAO_TUPLE_TUPLE_HPP
#define TAO_TUPLE_TUPLE_HPP
#include "../seq/config.hpp"
#include "../seq/exclusive_scan.hpp"
#include "../seq/inclusive_scan.hpp"
#include "../seq/integer_sequence.hpp"
#include "../seq/is_all.hpp"
#include "../seq/make_integer_sequence.hpp"
#include "../seq/map.hpp"
#include "../seq/minus.hpp"
#include "../seq/sum.hpp"
#include "../seq/type_by_index.hpp"
#include <memory>
#include <type_traits>
#include <utility>
#if( __cplusplus >= 201402L )
#define TAO_TUPLE_CONSTEXPR constexpr
#else
#define TAO_TUPLE_CONSTEXPR
#endif
#ifndef TAO_TUPLE_CUDA_ANNOTATE_COMMON
#ifdef __CUDACC__
#define TAO_TUPLE_CUDA_ANNOTATE_COMMON __host__ __device__
#else
#define TAO_TUPLE_CUDA_ANNOTATE_COMMON
#endif
#endif
// Ignore "calling a __host__ function from a __host__ _device__ function is not allowed" warnings
#ifndef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#ifdef __CUDACC__
#if _MSC_VER
#if __CUDAVER__ >= 75000
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN __pragma("nv_exec_check_disable")
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN __pragma("hd_warning_disable")
#endif
#else
#if __CUDAVER__ >= 75000
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN _Pragma("nv_exec_check_disable")
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN _Pragma("hd_warning_disable")
#endif
#endif
#else
#define TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#endif
#endif
namespace tao
{
template< typename... Ts >
struct tuple;
}
namespace std
{
// 20.4.2.8 Tuple traits [tuple.traits]
template< typename... Ts, typename A >
struct uses_allocator< tao::tuple< Ts... >, A > : true_type
{
};
} // namespace std
namespace tao
{
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::type_by_index_t< I, Ts... >& get( const tuple< Ts... >& ) noexcept;
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Ts... >& get( tuple< Ts... >& ) noexcept;
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Ts... >&& get( const tuple< Ts... >&& ) noexcept;
namespace impl
{
// TODO: std::pair support
// TODO: allocator support
using swallow = bool[];
template< typename T, typename >
struct dependent_type : T
{
};
template< bool B, typename T = void >
using enable_if_t = typename std::enable_if< B, T >::type;
// TODO: this is in namespace impl. is it harmless?
using std::swap;
template< typename T >
using is_nothrow_swappable = std::integral_constant< bool, noexcept( swap( std::declval< T& >(), std::declval< T& >() ) ) >;
#if __cplusplus >= 201402L
template< typename T >
using is_final = std::is_final< T >;
#else
template< typename T >
using is_final = std::integral_constant< bool, __is_final( T ) >;
#endif
template< bool, bool >
struct uses_alloc_ctor;
template< typename T, typename A, typename... As >
using uses_alloc_ctor_t = uses_alloc_ctor< std::uses_allocator< T, A >::value, std::is_constructible< T, std::allocator_arg_t, A, As... >::value >*;
template< std::size_t I, typename T, bool = std::is_empty< T >::value && !is_final< T >::value >
struct tuple_value
{
T value;
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAO_TUPLE_CUDA_ANNOTATE_COMMON
constexpr tuple_value() noexcept( std::is_nothrow_default_constructible< T >::value )
: value()
{
static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" );
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< bool B, typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< false, B >*, const A& )
: value()
{
static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" );
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, true >*, const A& a )
: value( std::allocator_arg_t(), a )
{
static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" );
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, false >*, const A& a )
: value( a )
{
static_assert( !std::is_reference< T >::value, "attempted to default construct a reference element in a tuple" );
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename U,
typename = impl::enable_if_t< !std::is_same< typename std::decay< U >::type, tuple_value >::value >,
typename = impl::enable_if_t< std::is_constructible< T, U >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_value( U&& v ) noexcept( std::is_nothrow_constructible< T, U >::value )
: value( std::forward< U >( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< bool B, typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< false, B >*, const A&, U&& v )
: value( std::forward< U >( v ) )
{
// TODO: Add check for rvalue to lvalue reference
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, true >*, const A& a, U&& v )
: value( std::allocator_arg_t(), a, std::forward< U >( v ) )
{
// TODO: Add check for rvalue to lvalue reference
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, false >*, const A& a, U&& v )
: value( std::forward< U >( v ), a )
{
// TODO: Add check for rvalue to lvalue reference
}
tuple_value( const tuple_value& ) = default;
tuple_value( tuple_value&& ) = default;
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_value& operator=( U&& v ) noexcept( std::is_nothrow_assignable< T&, U >::value )
{
value = std::forward< U >( v );
return *this;
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
void swap( tuple_value& v ) noexcept( is_nothrow_swappable< T >::value )
{
using std::swap;
swap( value, v.value );
}
TAO_TUPLE_CONSTEXPR
TAO_TUPLE_CUDA_ANNOTATE_COMMON
T& get_value() noexcept
{
return value;
}
TAO_TUPLE_CONSTEXPR
TAO_TUPLE_CUDA_ANNOTATE_COMMON
const T& get_value() const noexcept
{
return value;
}
};
template< std::size_t I, typename T >
struct tuple_value< I, T, true >
: private T
{
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
constexpr TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value() noexcept( std::is_nothrow_default_constructible< T >::value )
: T()
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< bool B, typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< false, B >*, const A& )
: T()
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, true >*, const A& a )
: T( std::allocator_arg_t(), a )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, false >*, const A& a )
: T( a )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename U,
typename = impl::enable_if_t< !std::is_same< typename std::decay< U >::type, tuple_value >::value >,
typename = impl::enable_if_t< std::is_constructible< T, U >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_value( U&& v ) noexcept( std::is_nothrow_constructible< T, U >::value )
: T( std::forward< U >( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< bool B, typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< false, B >*, const A&, U&& v )
: T( std::forward< U >( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, true >*, const A& a, U&& v )
: T( std::allocator_arg_t(), a, std::forward< U >( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A, typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_value( uses_alloc_ctor< true, false >*, const A& a, U&& v )
: T( std::forward< U >( v ), a )
{
}
tuple_value( const tuple_value& ) = default;
tuple_value( tuple_value&& ) = default;
template< typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_value& operator=( U&& v ) noexcept( std::is_nothrow_assignable< T&, U >::value )
{
T::operator=( std::forward< U >( v ) );
return *this;
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
void swap( tuple_value& v ) noexcept( is_nothrow_swappable< T >::value )
{
using std::swap;
swap( *this, v );
}
TAO_TUPLE_CONSTEXPR
TAO_TUPLE_CUDA_ANNOTATE_COMMON
T& get_value() noexcept
{
return static_cast< T& >( *this );
}
TAO_TUPLE_CONSTEXPR
TAO_TUPLE_CUDA_ANNOTATE_COMMON
const T& get_value() const noexcept
{
return static_cast< const T& >( *this );
}
};
template< typename, typename... >
struct tuple_base;
template< std::size_t... Is, typename... Ts >
struct tuple_base< seq::index_sequence< Is... >, Ts... >
: tuple_value< Is, Ts >...
{
constexpr tuple_base() = default;
template< typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple_base( Us&&... us )
: tuple_value< Is, Ts >( std::forward< Us >( us ) )...
{
}
template< typename A, typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base( std::allocator_arg_t, const A& a, Us&&... us )
: tuple_value< Is, Ts >( uses_alloc_ctor_t< Ts, A, Us >(), a, std::forward< Us >( us ) )...
{
}
tuple_base( const tuple_base& ) = default;
tuple_base( tuple_base&& ) = default;
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_base& operator=( const tuple_base& v ) noexcept( seq::is_all< std::is_nothrow_copy_assignable< Ts >::value... >::value )
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
( tuple_value< Is, Ts >::operator=( static_cast< tuple_value< Is, Ts >& >( v ).get_value() ), ... );
#else
(void)swallow{ ( tuple_value< Is, Ts >::operator=( static_cast< tuple_value< Is, Ts >& >( v ).get_value() ), true )..., true };
#endif
return *this;
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple_base& operator=( tuple_base&& v ) noexcept( seq::is_all< std::is_nothrow_move_assignable< Ts >::value... >::value )
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
( tuple_value< Is, Ts >::operator=( std::forward< Ts >( static_cast< tuple_value< Is, Ts >& >( v ).get_value() ) ), ... );
#else
(void)swallow{ ( tuple_value< Is, Ts >::operator=( static_cast< tuple_value< Is, Ts >& >( v ) ), true )..., true };
#endif
return *this;
}
template< typename... Us >
TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base& operator=( const tuple< Us... >& v ) noexcept( seq::is_all< std::is_nothrow_assignable< Ts&, const Us& >::value... >::value )
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
( tuple_value< Is, Ts >::operator=( get< Is >( v ) ), ... );
#else
(void)swallow{ ( tuple_value< Is, Ts >::operator=( get< Is >( v ) ), true )..., true };
#endif
return *this;
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename... Us >
TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple_base& operator=( tuple< Us... >&& v ) noexcept( seq::is_all< std::is_nothrow_assignable< Ts&, Us&& >::value... >::value )
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
( tuple_value< Is, Ts >::operator=( get< Is >( std::move( v ) ) ), ... );
#else
(void)swallow{ ( tuple_value< Is, Ts >::operator=( get< Is >( std::move( v ) ) ), true )..., true };
#endif
return *this;
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
void swap( tuple_base& v ) noexcept( seq::is_all< impl::is_nothrow_swappable< Ts >::value... >::value )
{
#ifdef TAO_SEQ_FOLD_EXPRESSIONS
( static_cast< tuple_value< Is, Ts >& >( *this ).swap( static_cast< tuple_value< Is, Ts >& >( v ) ), ... );
#else
(void)swallow{ ( static_cast< tuple_value< Is, Ts >& >( *this ).swap( static_cast< tuple_value< Is, Ts >& >( v ) ), true )..., true };
#endif
}
};
} // namespace impl
// 20.4.2 Class template tuple [tuple.tuple]
// tuple
template< typename... Ts >
struct tuple
{
private:
using base_t = impl::tuple_base< seq::index_sequence_for< Ts... >, Ts... >;
base_t base;
template< std::size_t I, typename... Us >
friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::type_by_index_t< I, Us... >& get( const tuple< Us... >& ) noexcept;
template< std::size_t I, typename... Us >
friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Us... >& get( tuple< Us... >& ) noexcept;
template< std::size_t I, typename... Us >
friend TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Us... >&& get( tuple< Us... >&& ) noexcept;
public:
// 20.4.2.1 Construction [tuple.cnstr]
// TODO: Move this templated condition to base?
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename dummy = void,
typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_default_constructible< Ts >, dummy >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON constexpr tuple() noexcept( seq::is_all< std::is_nothrow_default_constructible< Ts >::value... >::value )
: base()
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename dummy = void,
typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_copy_constructible< Ts >, dummy >::value... >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( const Ts&... ts ) noexcept( seq::is_all< std::is_nothrow_copy_constructible< Ts >::value... >::value )
: base( ts... )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( Us&&... us ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, Us&& >::value... >::value )
: base( std::forward< Us >( us )... )
{
}
tuple( const tuple& ) = default;
tuple( tuple&& ) = default;
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, const Us& >::value... >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( const tuple< Us... >& v ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, const Us& >::value... >::value )
: base( v )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON explicit tuple( tuple< Us... >&& v ) noexcept( seq::is_all< std::is_nothrow_constructible< Ts, Us&& >::value... >::value )
: base( std::move( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A,
typename dummy = void,
typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_default_constructible< Ts >, dummy >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a )
: base( std::allocator_arg_t(), a )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A,
typename dummy = void,
typename = impl::enable_if_t< seq::is_all< impl::dependent_type< std::is_copy_constructible< Ts >, dummy >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, const Ts&... ts )
: base( std::allocator_arg_t(), a, ts... )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A,
typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, Us&&... us )
: base( std::allocator_arg_t(), a, std::forward< Us >( us )... )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, const tuple& v )
: base( std::allocator_arg_t(), a, v )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, tuple&& v )
: base( std::allocator_arg_t(), a, std::move( v ) )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A,
typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, const Us& >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, const tuple< Us... >& v )
: base( std::allocator_arg_t(), a, v )
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A,
typename... Us,
typename = impl::enable_if_t< sizeof...( Us ) == sizeof...( Ts ) >,
typename = impl::enable_if_t< seq::is_all< std::is_constructible< Ts, Us&& >::value... >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& a, tuple< Us... >&& v )
: base( std::allocator_arg_t(), a, std::move( v ) )
{
}
// 20.4.2.2 Assignment [tuple.assign]
template< typename T,
typename = impl::enable_if_t< std::is_assignable< base_t&, T >::value > >
TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple& operator=( T&& v ) noexcept( std::is_nothrow_assignable< base_t&, T >::value )
{
base = std::forward< T >( v );
return *this;
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple& operator=( const tuple& v )
noexcept( std::is_nothrow_assignable< base_t&, tuple >::value )
{
base = v;
return *this;
}
// 20.4.2.3 swap [tuple.swap]
TAO_TUPLE_CUDA_ANNOTATE_COMMON
void swap( tuple& v ) noexcept( noexcept( base.swap( v.base ) ) )
{
base.swap( v.base );
}
};
template<>
struct tuple<>
{
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
TAO_TUPLE_CUDA_ANNOTATE_COMMON
constexpr tuple() noexcept {}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A& ) noexcept
{
}
TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
template< typename A >
TAO_TUPLE_CUDA_ANNOTATE_COMMON
tuple( std::allocator_arg_t, const A&, const tuple& ) noexcept
{
}
TAO_TUPLE_CUDA_ANNOTATE_COMMON
void swap( tuple& ) noexcept {}
};
// 20.4.2.4 Tuple creation functions [tuple.creation]
// ignore helper
namespace impl
{
struct ignore_t
{
template< typename U >
TAO_TUPLE_CUDA_ANNOTATE_COMMON ignore_t& operator=( U&& )
{
return *this;
}
};
} // namespace impl
// ignore
const impl::ignore_t ignore{};
// make_tuple helper
namespace impl
{
template< typename T >
struct make_tuple_return
{
using type = T;
};
template< typename T >
struct make_tuple_return< std::reference_wrapper< T > >
{
using type = T&;
};
template< typename T >
using make_tuple_return_t = typename make_tuple_return< T >::type;
} // namespace impl
// make_tuple
template< typename... Ts, typename R = tuple< impl::make_tuple_return_t< typename std::decay< Ts >::type >... > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R make_tuple( Ts&&... ts )
{
return R( std::forward< Ts >( ts )... );
}
// forward_as_tuple
template< typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple< Ts&&... > forward_as_tuple( Ts&&... ts ) noexcept
{
return tuple< Ts&&... >( std::forward< Ts >( ts )... );
}
// tie
template< typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON tuple< Ts&... > tie( Ts&... ts ) noexcept
{
return tuple< Ts&... >( ts... );
}
// tuple_cat is found at the end, as it requires access to tuple_element_t and get<I>
// 20.4.2.5 Tuple helper classes [tuple.helper]
// tuple_size
template< typename T >
struct tuple_size;
template< typename T >
struct tuple_size< const T >
: tuple_size< T >
{
};
template< typename T >
struct tuple_size< volatile T >
: tuple_size< T >
{
};
template< typename T >
struct tuple_size< const volatile T >
: tuple_size< T >
{
};
template< typename... Ts >
struct tuple_size< tuple< Ts... > >
: std::integral_constant< std::size_t, sizeof...( Ts ) >
{
};
// tuple_element
template< std::size_t I, typename T >
struct tuple_element;
template< std::size_t I, typename T >
struct tuple_element< I, const T >
: tuple_element< I, T >
{
};
template< std::size_t I, typename T >
struct tuple_element< I, volatile T >
: tuple_element< I, T >
{
};
template< std::size_t I, typename T >
struct tuple_element< I, const volatile T >
: tuple_element< I, T >
{
};
template< std::size_t I, typename... Ts >
struct tuple_element< I, tuple< Ts... > >
: seq::type_by_index< I, Ts... >
{
};
#if __cplusplus >= 201402L
template< std::size_t I, typename T >
using tuple_element_t = typename tuple_element< I, T >::type;
#endif
// 20.4.2.6 Element access [tuple.elem]
// get<I>
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const seq::type_by_index_t< I, Ts... >& get( const tuple< Ts... >& v ) noexcept
{
return static_cast< const impl::tuple_value< I, seq::type_by_index_t< I, Ts... > >& >( v.base ).get_value();
}
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Ts... >& get( tuple< Ts... >& v ) noexcept
{
return static_cast< impl::tuple_value< I, seq::type_by_index_t< I, Ts... > >& >( v.base ).get_value();
}
template< std::size_t I, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON seq::type_by_index_t< I, Ts... >&& get( tuple< Ts... >&& v ) noexcept
{
using type = seq::type_by_index_t< I, Ts... >;
return static_cast< type&& >( static_cast< impl::tuple_value< I, type >& >( v.base ).get_value() );
}
// get<T> helper
namespace impl
{
template< typename T, typename... Ts >
using count_of = seq::sum< std::size_t, ( std::is_same< T, Ts >::value ? 1 : 0 )... >;
template< typename, typename, typename... >
struct index_of_impl;
template< std::size_t... Is, typename T, typename... Ts >
struct index_of_impl< seq::index_sequence< Is... >, T, Ts... >
: seq::sum< std::size_t, ( std::is_same< T, Ts >::value ? Is : 0 )... >
{
static_assert( count_of< T, Ts... >::value > 0, "T not found within Ts..." );
static_assert( count_of< T, Ts... >::value < 2, "T must be unique within Ts..." );
};
template< typename T, typename... Ts >
using index_of = index_of_impl< seq::index_sequence_for< Ts... >, T, Ts... >;
} // namespace impl
// get<T>
template< typename T, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON const T& get( const tuple< Ts... >& v ) noexcept
{
return get< impl::index_of< T, Ts... >::value >( v );
}
template< typename T, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON T& get( tuple< Ts... >& v ) noexcept
{
return get< impl::index_of< T, Ts... >::value >( v );
}
template< typename T, typename... Ts >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON T&& get( tuple< Ts... >&& v ) noexcept
{
return get< impl::index_of< T, Ts... >::value >( std::move( v ) );
}
// 20.4.2.7 Relational operators [tuple.rel]
// operators helper
// here, recursion seems to be the better choice, especially wrt constexpr
namespace impl
{
template< std::size_t I, std::size_t S >
struct tuple_equal;
template< std::size_t I >
struct tuple_equal< I, I >
{
template< typename T, typename U >
static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T&, const U& ) noexcept
{
return true;
}
};
template< std::size_t I, std::size_t S >
struct tuple_equal
{
template< typename T, typename U >
static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T& lhs, const U& rhs ) noexcept( noexcept( static_cast< bool >( get< I >( lhs ) == get< I >( rhs ) ) && tuple_equal< I + 1, S >::apply( lhs, rhs ) ) )
{
return static_cast< bool >( get< I >( lhs ) == get< I >( rhs ) ) && tuple_equal< I + 1, S >::apply( lhs, rhs );
}
};
template< std::size_t I, std::size_t S >
struct tuple_less;
template< std::size_t I >
struct tuple_less< I, I >
{
template< typename T, typename U >
static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T&, const U& ) noexcept
{
return false;
}
};
template< std::size_t I, std::size_t S >
struct tuple_less
{
template< typename T, typename U >
static TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool apply( const T& lhs, const U& rhs ) noexcept( noexcept( static_cast< bool >( get< I >( lhs ) < get< I >( rhs ) ) || ( !static_cast< bool >( get< I >( rhs ) < get< I >( lhs ) ) && tuple_less< I + 1, S >::apply( lhs, rhs ) ) ) )
{
return static_cast< bool >( get< I >( lhs ) < get< I >( rhs ) ) || ( !static_cast< bool >( get< I >( rhs ) < get< I >( lhs ) ) && tuple_less< I + 1, S >::apply( lhs, rhs ) );
}
};
} // namespace impl
// operators
template< typename... Ts, typename... Us, typename = impl::enable_if_t< sizeof...( Ts ) == sizeof...( Us ) > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator==( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( impl::tuple_equal< 0, sizeof...( Ts ) >::apply( lhs, rhs ) ) )
{
return impl::tuple_equal< 0, sizeof...( Ts ) >::apply( lhs, rhs );
}
template< typename... Ts, typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator!=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( lhs == rhs ) ) )
{
return !( lhs == rhs );
}
template< typename... Ts, typename... Us, typename = impl::enable_if_t< sizeof...( Ts ) == sizeof...( Us ) > >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator<( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( impl::tuple_less< 0, sizeof...( Ts ) >::apply( lhs, rhs ) ) )
{
return impl::tuple_less< 0, sizeof...( Ts ) >::apply( lhs, rhs );
}
template< typename... Ts, typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator>=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( lhs < rhs ) ) )
{
return !( lhs < rhs );
}
template< typename... Ts, typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator>( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( rhs < lhs ) )
{
return rhs < lhs;
}
template< typename... Ts, typename... Us >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON bool operator<=( const tuple< Ts... >& lhs, const tuple< Us... >& rhs ) noexcept( noexcept( !( rhs < lhs ) ) )
{
return !( rhs < lhs );
}
// 20.4.2.9 Tuple specialized algorithms [tuple.special]
// swap
template< typename... Ts >
TAO_TUPLE_CUDA_ANNOTATE_COMMON void swap( tuple< Ts... >& lhs, tuple< Ts... >& rhs ) noexcept( noexcept( lhs.swap( rhs ) ) )
{
lhs.swap( rhs );
}
// (continued:) 20.4.2.4 Tuple creation functions [tuple.creation]
// tuple_cat helper
namespace impl
{
template< std::size_t M, std::size_t... Ns >
struct count_less_or_equal
: seq::sum< std::size_t, ( ( Ns <= M ) ? 1 : 0 )... >
{
};
template< typename, typename >
struct expand;
template< std::size_t... Is, std::size_t... Ns >
struct expand< seq::index_sequence< Is... >, seq::index_sequence< Ns... > >
{
using type = seq::index_sequence< count_less_or_equal< Is, Ns... >::value... >;
};
template< typename I, typename S >
using expand_t = typename expand< I, S >::type;
template< typename... >
struct tuple_cat_result;
template< std::size_t... Os, std::size_t... Is, typename... Ts >
struct tuple_cat_result< seq::index_sequence< Os... >, seq::index_sequence< Is... >, Ts... >
{
using type = tuple< typename tuple_element< Is, seq::type_by_index_t< Os, Ts... > >::type... >;
};
template< typename... Ts >
using tuple_cat_result_t = typename tuple_cat_result< Ts... >::type;
template< typename... Ts >
struct tuple_cat_helper
{
using tuple_size_sequence = seq::index_sequence< tuple_size< Ts >::value... >;
using result_index_sequence = seq::make_index_sequence< seq::sum< tuple_size_sequence >::value >;
using outer_index_sequence = expand_t< result_index_sequence, seq::inclusive_scan_t< tuple_size_sequence > >;
using inner_index_sequence = seq::minus_t< result_index_sequence, seq::map_t< outer_index_sequence, seq::exclusive_scan_t< tuple_size_sequence > > >;
using result_type = tuple_cat_result_t< outer_index_sequence, inner_index_sequence, Ts... >;
};
template< typename R, std::size_t... Os, std::size_t... Is, typename T >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R tuple_cat( seq::index_sequence< Os... >, seq::index_sequence< Is... >, T v )
{
return R( get< Is >( get< Os >( v ) )... );
}
} // namespace impl
// tuple_cat
template< typename... Ts, typename H = impl::tuple_cat_helper< typename std::remove_reference< Ts >::type... >, typename R = typename H::result_type >
TAO_TUPLE_CONSTEXPR TAO_TUPLE_CUDA_ANNOTATE_COMMON R tuple_cat( Ts&&... ts )
{
return impl::tuple_cat< R >( typename H::outer_index_sequence(), typename H::inner_index_sequence(), tao::forward_as_tuple( std::forward< Ts >( ts )... ) );
}
} // namespace tao
#undef TAO_TUPLE_CONSTEXPR
#undef TAO_TUPLE_CUDA_ANNOTATE_COMMON
#undef TAO_TUPLE_SUPPRESS_NVCC_HD_WARN
#endif

@ -9,7 +9,6 @@
##============================================================================
set(headers
DecayHelpers.h
DispatcherBase.h
MaskBase.h
Placeholders.h

@ -28,7 +28,8 @@
#include <vtkm/internal/brigand.hpp>
#include <vtkm/worklet/internal/DecayHelpers.h>
#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/worklet/internal/WorkletBase.h>
#include <sstream>
@ -156,7 +157,7 @@ struct ReportValueOnError<Value, true> : std::true_type
template <typename Type, typename State>
struct DetermineIfHasDynamicParameter
{
using T = remove_pointer_and_decay<Type>;
using T = vtkm::internal::remove_pointer_and_decay<Type>;
using DynamicTag = typename vtkm::cont::internal::DynamicTransformTraits<T>::DynamicTag;
using isDynamic =
typename std::is_same<DynamicTag, vtkm::cont::internal::DynamicTransformTagCastAndCall>::type;
@ -312,7 +313,7 @@ struct DispatcherBaseTransportFunctor
{
using TransportTag =
typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag;
using T = remove_pointer_and_decay<ControlParameter>;
using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>;
using TransportType = typename vtkm::cont::arg::Transport<TransportTag, T, Device>;
using type = typename TransportType::ExecObjectType;
};
@ -324,7 +325,7 @@ struct DispatcherBaseTransportFunctor
{
using TransportTag =
typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag;
using T = remove_pointer_and_decay<ControlParameter>;
using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>;
vtkm::cont::arg::Transport<TransportTag, T, Device> transport;
not_nullptr(invokeData, Index);
@ -413,7 +414,7 @@ struct for_each_dynamic_arg
void operator()(const Trampoline& trampoline, ContParams&& sig, T&& t, Args&&... args) const
{
//Determine that state of T when it is either a `cons&` or a `* const&`
using Type = remove_pointer_and_decay<T>;
using Type = vtkm::internal::remove_pointer_and_decay<T>;
using tag = typename vtkm::cont::internal::DynamicTransformTraits<Type>::DynamicTag;
//convert the first item to a known type
convert_arg<LeftToProcess>(
@ -498,7 +499,8 @@ private:
template <typename... Args>
VTKM_CONT void StartInvoke(Args&&... args) const
{
using ParameterInterface = vtkm::internal::FunctionInterface<void(remove_cvref<Args>...)>;
using ParameterInterface =
vtkm::internal::FunctionInterface<void(vtkm::internal::remove_cvref<Args>...)>;
VTKM_STATIC_ASSERT_MSG(ParameterInterface::ARITY == NUM_INVOKE_PARAMS,
"Dispatcher Invoke called with wrong number of arguments.");
@ -543,7 +545,8 @@ private:
template <typename... Args>
VTKM_CONT void StartInvokeDynamic(std::false_type, Args&&... args) const
{
using ParameterInterface = vtkm::internal::FunctionInterface<void(remove_cvref<Args>...)>;
using ParameterInterface =
vtkm::internal::FunctionInterface<void(vtkm::internal::remove_cvref<Args>...)>;
//Nothing requires a conversion from dynamic to static types, so
//next we need to verify that each argument's type is correct. If not
@ -564,7 +567,8 @@ private:
static_assert(isAllValid::value == expectedLen::value,
"All arguments failed the TypeCheck pass");
auto fi = vtkm::internal::make_FunctionInterface<void, remove_cvref<Args>...>(args...);
auto fi =
vtkm::internal::make_FunctionInterface<void, vtkm::internal::remove_cvref<Args>...>(args...);
auto ivc = vtkm::internal::Invocation<ParameterInterface,
ControlInterface,
ExecutionInterface,

@ -10,8 +10,8 @@
#ifndef vtk_m_worklet_internal_MaskBase_h
#define vtk_m_worklet_internal_MaskBase_h
#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/worklet/internal/DecayHelpers.h>
namespace vtkm
{
@ -30,7 +30,7 @@ struct VTKM_ALWAYS_EXPORT MaskBase
};
template <typename T>
using is_mask = std::is_base_of<MaskBase, remove_cvref<T>>;
using is_mask = std::is_base_of<MaskBase, vtkm::internal::remove_cvref<T>>;
}
}
}

@ -10,8 +10,7 @@
#ifndef vtk_m_worklet_internal_Placeholders_h
#define vtk_m_worklet_internal_Placeholders_h
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <vtkmstd/integer_sequence.h>
#include <type_traits>
@ -42,7 +41,7 @@ struct FunctionSigArity<R(ArgTypes...)>
//============================================================================
template <int... Args>
auto DefaultSigGenerator(tao::seq::integer_sequence<int, 0, Args...>) -> void (*)(Arg<Args>...);
auto DefaultSigGenerator(vtkmstd::integer_sequence<int, 0, Args...>) -> void (*)(Arg<Args>...);
/**
* Given a desired length will generate the default/assumed ExecutionSignature.
@ -56,7 +55,7 @@ auto DefaultSigGenerator(tao::seq::integer_sequence<int, 0, Args...>) -> void (*
template <int Length>
struct DefaultExecSig
{
using seq = tao::seq::make_integer_sequence<int, Length + 1>;
using seq = vtkmstd::make_integer_sequence<int, Length + 1>;
using type = typename std::remove_pointer<decltype(DefaultSigGenerator(seq{}))>::type;
};
template <>
@ -80,6 +79,19 @@ struct DefaultExecSig<4>
using type = void(Arg<1>, Arg<2>, Arg<3>, Arg<4>);
};
template <bool HasExecSig_, typename Sig_>
struct ExecSigQuery
{
static constexpr bool HasExecSig = HasExecSig_;
using Sig = Sig_;
};
template <typename U, typename S = decltype(std::declval<typename U::ExecutionSignature>())>
static ExecSigQuery<true, typename U::ExecutionSignature> get_exec_sig(int);
template <typename U>
static ExecSigQuery<false, void> get_exec_sig(...);
//============================================================================
/**
* Given a worklet this will produce a typedef `ExecutionSignature` that is
@ -98,21 +110,15 @@ struct DefaultExecSig<4>
template <typename WorkletType>
struct GetExecSig
{
template <typename U, typename S = decltype(std::declval<typename U::ExecutionSignature>())>
static vtkmstd::tuple<std::true_type, typename U::ExecutionSignature> get_exec_sig(int);
template <typename U>
static vtkmstd::tuple<std::false_type, std::false_type> get_exec_sig(...);
using cont_sig = typename WorkletType::ControlSignature;
using cont_sig_info = vtkm::placeholders::FunctionSigArity<cont_sig>;
using result = decltype(get_exec_sig<WorkletType>(0));
using has_explicit_exec_sig = typename vtkmstd::tuple_element<0, result>::type;
static constexpr bool has_explicit_exec_sig = result::HasExecSig;
using ExecutionSignature = typename std::conditional<
has_explicit_exec_sig::value,
typename vtkmstd::tuple_element<1, result>::type,
has_explicit_exec_sig,
typename result::Sig,
typename vtkm::placeholders::DefaultExecSig<cont_sig_info::value>::type>::type;
};
}

@ -10,8 +10,8 @@
#ifndef vtk_m_worklet_internal_ScatterBase_h
#define vtk_m_worklet_internal_ScatterBase_h
#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/worklet/internal/DecayHelpers.h>
namespace vtkm
{
@ -29,7 +29,7 @@ struct VTKM_ALWAYS_EXPORT ScatterBase
};
template <typename T>
using is_scatter = std::is_base_of<ScatterBase, remove_cvref<T>>;
using is_scatter = std::is_base_of<ScatterBase, vtkm::internal::remove_cvref<T>>;
}
}
}

18
vtkmstd/CMakeLists.txt Normal file

@ -0,0 +1,18 @@
##============================================================================
## 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.
##============================================================================
set(headers
aligned_union.h
integer_sequence.h
is_trivially_copyable.h
void_t.h
)
vtkm_declare_headers(${headers})

69
vtkmstd/aligned_union.h Normal file

@ -0,0 +1,69 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_std_aligned_union_h
#define vtk_m_std_aligned_union_h
#include <vtkm/internal/Configure.h>
#include <type_traits>
#if defined(VTKM_USING_GLIBCXX_4)
#include <algorithm>
namespace vtkmstd
{
template <std::size_t... Xs>
struct max_size;
template <std::size_t X>
struct max_size<X>
{
static constexpr std::size_t value = X;
};
template <std::size_t X0, std::size_t... Xs>
struct max_size<X0, Xs...>
{
static constexpr std::size_t other_value = max_size<Xs...>::value;
static constexpr std::size_t value = (other_value > X0) ? other_value : X0;
};
// This is to get around an apparent bug in GCC 4.8 where alianas(x) does not
// seem to work when x is a constexpr. See
// https://stackoverflow.com/questions/29879609/g-complains-constexpr-function-is-not-a-constant-expression
template <std::size_t Alignment, std::size_t Size>
struct aligned_data_block
{
alignas(Alignment) char _s[Size];
};
template <std::size_t Len, class... Types>
struct aligned_union
{
static constexpr std::size_t alignment_value = vtkmstd::max_size<alignof(Types)...>::value;
using type =
vtkmstd::aligned_data_block<alignment_value, vtkmstd::max_size<Len, sizeof(Types)...>::value>;
};
} // namespace vtkmstd
#else // NOT VTKM_USING_GLIBCXX_4
namespace vtkmstd
{
using std::aligned_union;
} // namespace vtkmstd
#endif // NOT VTKM_USING_GLIBCXX_4
#endif //vtk_m_std_aligned_union_h

234
vtkmstd/integer_sequence.h Normal file

@ -0,0 +1,234 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_std_integer_sequence_h
#define vtk_m_std_integer_sequence_h
#include <vtkm/internal/Configure.h>
#include <vtkm/StaticAssert.h>
#include <utility>
#if defined(__cpp_lib_integer_sequence)
#define VTK_M_USE_STD_INTEGER_SEQUENCE
#elif (__cplusplus >= 201402L)
#define VTK_M_USE_STD_INTEGER_SEQUENCE
#elif defined(VTKM_MSVC)
#define VTK_M_USE_STD_INTEGER_SEQUENCE
#endif
#if (__cplusplus >= 201402L)
#define VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
#elif defined(VTKM_MSVC) && (_MSC_FULL_VER >= 190023918)
#define VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
#endif
namespace vtkmstd
{
#ifndef VTK_M_USE_STD_INTEGER_SEQUENCE
template <typename T, T... Ns>
struct integer_sequence
{
using value_type = T;
static constexpr std::size_t size() noexcept { return sizeof...(Ns); }
};
template <std::size_t... Ns>
using index_sequence = integer_sequence<std::size_t, Ns...>;
#else // VTK_M_USE_STD_INTEGER_SEQUENCE
using std::integer_sequence;
using std::index_sequence;
#endif // VTK_M_USE_STD_INTEGER_SEQUENCE
#ifndef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
namespace detail
{
// Implementation note: ideally these implementation classes would define "Num"
// as the type for the sequence (i.e. T). However, compilers have trouble
// resolving template partial specialization for a number whose type is one of
// the other template parameters. (Most compilers allow you to specify them in
// an integral_constant, but versions of GCC fail at that, too.) Instead, we are
// using std::size_t for the num, which should be large enough.
using SeqSizeT = std::size_t;
template <typename T, SeqSizeT Num>
struct MakeSequenceImpl;
template <typename Sequence>
struct DoubleSequence;
template <typename T, T... Ns>
struct DoubleSequence<vtkmstd::integer_sequence<T, Ns...>>
{
using type = vtkmstd::integer_sequence<T, Ns..., T(sizeof...(Ns)) + Ns...>;
};
template <typename Sequence1, typename Sequence2>
struct CombineSequences;
template <typename T, T... N1s, T... N2s>
struct CombineSequences<vtkmstd::integer_sequence<T, N1s...>, vtkmstd::integer_sequence<T, N2s...>>
{
using type = vtkmstd::integer_sequence<T, N1s..., T(sizeof...(N1s)) + N2s...>;
};
template <bool CanDouble, SeqSizeT Num, typename Sequence>
struct ExpandSequence;
template <typename T, SeqSizeT Num, T... Ns>
struct ExpandSequence<true, Num, vtkmstd::integer_sequence<T, Ns...>>
{
static constexpr SeqSizeT OldSize = sizeof...(Ns);
static constexpr SeqSizeT RemainingAfter = Num - OldSize;
static constexpr bool CanDoubleNext = RemainingAfter >= OldSize * 2;
using type = typename ExpandSequence<
CanDoubleNext,
RemainingAfter,
typename DoubleSequence<vtkmstd::integer_sequence<T, Ns...>>::type>::type;
};
template <typename T, SeqSizeT Num, T... Ns>
struct ExpandSequence<false, Num, vtkmstd::integer_sequence<T, Ns...>>
{
using type = typename CombineSequences<vtkmstd::integer_sequence<T, Ns...>,
typename MakeSequenceImpl<T, Num>::type>::type;
};
template <typename T>
struct MakeSequenceImpl<T, 0>
{
using type = vtkmstd::integer_sequence<T>;
};
template <typename T>
struct MakeSequenceImpl<T, 1>
{
using type = vtkmstd::integer_sequence<T, 0>;
};
template <typename T>
struct MakeSequenceImpl<T, 2>
{
using type = vtkmstd::integer_sequence<T, 0, 1>;
};
template <typename T>
struct MakeSequenceImpl<T, 3>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2>;
};
template <typename T>
struct MakeSequenceImpl<T, 4>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3>;
};
template <typename T>
struct MakeSequenceImpl<T, 5>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4>;
};
template <typename T>
struct MakeSequenceImpl<T, 6>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5>;
};
template <typename T>
struct MakeSequenceImpl<T, 7>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6>;
};
template <typename T>
struct MakeSequenceImpl<T, 8>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7>;
};
template <typename T>
struct MakeSequenceImpl<T, 9>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8>;
};
template <typename T>
struct MakeSequenceImpl<T, 10>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9>;
};
template <typename T>
struct MakeSequenceImpl<T, 11>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10>;
};
template <typename T>
struct MakeSequenceImpl<T, 12>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11>;
};
template <typename T>
struct MakeSequenceImpl<T, 13>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>;
};
template <typename T>
struct MakeSequenceImpl<T, 14>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>;
};
template <typename T>
struct MakeSequenceImpl<T, 15>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14>;
};
template <typename T>
struct MakeSequenceImpl<T, 16>
{
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>;
};
template <typename T, SeqSizeT Num>
struct MakeSequenceImpl
{
VTKM_STATIC_ASSERT(Num >= 16);
VTKM_STATIC_ASSERT_MSG(Num < (1 << 20), "Making an unexpectedly long integer sequence.");
using type =
typename ExpandSequence<(Num >= 32), Num - 16, typename MakeSequenceImpl<T, 16>::type>::type;
};
} // namespace detail
template <typename T, T N>
using make_integer_sequence =
typename detail::MakeSequenceImpl<T, static_cast<detail::SeqSizeT>(N)>::type;
template <std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
#else // VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
using std::make_integer_sequence;
using std::make_index_sequence;
#endif // VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
} // namespace vtkmstd
#ifdef VTK_M_USE_STD_INTEGER_SEQUENCE
#undef VTK_M_USE_STD_INTEGER_SEQUENCE
#endif
#ifdef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
#undef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE
#endif
#endif //vtk_m_std_integer_sequence_h

@ -0,0 +1,41 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_std_is_trivially_copyable_h
#define vtk_m_std_is_trivially_copyable_h
#include <type_traits>
#if defined(VTKM_USING_GLIBCXX_4)
namespace vtkmstd
{
// GCC 4.8 and 4.9 standard library does not support std::is_trivially_copyable.
// There is no relyable way to get this information (since it has to come special from
// the compiler). For our purposes, we will report as nothing being trivially copyable,
// which causes us to call the constructors with everything. This should be fine unless
// some other part of the compiler is trying to check for trivial copies (perhaps nvcc
// on top of GCC 4.8).
template <typename>
struct is_trivially_copyable : std::false_type
{
};
} // namespace vtkmstd
#else // NOT VTKM_USING_GLIBCXX_4
namespace vtkmstd
{
using std::is_trivially_copyable;
} // namespace vtkmstd
#endif
#endif //vtk_m_std_is_trivially_copyable_h

40
vtkmstd/void_t.h Normal file

@ -0,0 +1,40 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_std_void_t_h
#define vtk_m_std_void_t_h
#include <vtkm/internal/Configure.h>
namespace vtkmstd
{
/// Implementation of std::void_t (C++17):
/// Allows for specialization of class templates based on members of template
/// parameters.
#if defined(VTKM_GCC) && (__GNUC__ < 5)
// Due to a defect in the wording (CWG 1558) unused parameters in alias templates
// were not guaranteed to ensure SFINAE, and therefore would consider everything
// to match the 'true' side. For VTK-m the only known compiler that implemented
// this defect is GCC < 5.
template <class... T>
struct void_pack
{
using type = void;
};
template <class... T>
using void_t = typename void_pack<T...>::type;
#else
template <typename...>
using void_t = void;
#endif
} // end namespace vtkmstd
#endif //vtk_m_std_void_t_h