2014-04-10 19:35:06 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2014-04-10 19:35:06 +00:00
|
|
|
// 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.
|
|
|
|
//============================================================================
|
2014-10-08 16:07:08 +00:00
|
|
|
#ifndef vtk_m_internal_FunctionInterface_h
|
|
|
|
#define vtk_m_internal_FunctionInterface_h
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2020-07-14 17:35:46 +00:00
|
|
|
#include <vtkm/Deprecated.h>
|
2014-04-10 19:35:06 +00:00
|
|
|
#include <vtkm/Types.h>
|
|
|
|
|
2014-06-25 22:03:44 +00:00
|
|
|
#include <vtkm/internal/FunctionInterfaceDetailPre.h>
|
2017-05-18 14:51:24 +00:00
|
|
|
#include <vtkm/internal/IndexTag.h>
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2017-02-13 19:31:20 +00:00
|
|
|
#include <utility>
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace internal
|
|
|
|
{
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename OriginalSignature, typename Transform>
|
2014-05-06 19:28:08 +00:00
|
|
|
struct FunctionInterfaceStaticTransformType;
|
|
|
|
|
2014-04-10 19:35:06 +00:00
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
2014-06-06 21:20:50 +00:00
|
|
|
/// \brief Holds parameters and result of a function.
|
|
|
|
///
|
|
|
|
/// To make VTK-m easier for the end user developer, the
|
2017-09-21 23:14:55 +00:00
|
|
|
/// \c Invoke method of dispatchers takes an arbitrary amount of
|
2014-06-06 21:20:50 +00:00
|
|
|
/// arguments that get transformed and swizzled into arguments and return value
|
|
|
|
/// for a worklet operator. In between these two invocations a complicated
|
|
|
|
/// series of transformations and operations can occur.
|
|
|
|
///
|
|
|
|
/// Supporting arbitrary function and template arguments is difficult and
|
2019-11-26 19:26:32 +00:00
|
|
|
/// really requires separate implementations for pre-C++11 and C++11 versions of
|
|
|
|
/// compilers. Thus, variadic template arguments are, at this point in time,
|
2014-06-06 21:20:50 +00:00
|
|
|
/// something to be avoided when possible. The intention of \c
|
2019-11-26 19:26:32 +00:00
|
|
|
/// FunctionInterface is to collect most of the variadic template code into one
|
2014-06-06 21:20:50 +00:00
|
|
|
/// place. The \c FunctionInterface template class takes a function signature,
|
|
|
|
/// which can have a variable number of arguments. The \c FunctionInterface
|
|
|
|
/// will hold in its state a copy of all input parameters (regardless of number
|
2017-09-25 13:57:23 +00:00
|
|
|
/// or type) and the return value if it exists (i.e. non-nullptr) and the function
|
2014-06-06 21:20:50 +00:00
|
|
|
/// has been invoked. This means that all arguments can be passed around in a
|
|
|
|
/// single object so that objects and functions dealing with these variadic
|
|
|
|
/// parameters can be templated on a single type (the type of \c
|
|
|
|
/// FunctionInterface).
|
|
|
|
///
|
|
|
|
/// Note that the indexing of the parameters in a \c FunctionInterface starts
|
|
|
|
/// at 1. You can think of the return value being the parameter at index 0,
|
|
|
|
/// even if there is no return value. Although this is uncommon in C++, it
|
|
|
|
/// matches better the parameter indexing for other classes that deal with
|
|
|
|
/// function signatures.
|
|
|
|
///
|
|
|
|
/// The \c FunctionInterface contains several ways to invoke a functor whose
|
2014-11-12 15:53:03 +00:00
|
|
|
/// parameters match those of the function interface. This allows you to
|
|
|
|
/// complete the transition of calling an arbitrary function (like a worklet).
|
2014-06-06 21:20:50 +00:00
|
|
|
///
|
2014-11-12 15:53:03 +00:00
|
|
|
/// The following is a rundown of how a \c FunctionInterface is created and
|
|
|
|
/// used. See the independent documentation for more details.
|
2014-06-06 21:20:50 +00:00
|
|
|
///
|
|
|
|
/// Use the \c make_FunctionInterface function to create a \c FunctionInterface
|
|
|
|
/// and initialize the state of all the parameters. \c make_FunctionInterface
|
|
|
|
/// takes a variable number of arguments, one for each parameter. Since the
|
|
|
|
/// return type is not specified as an argument, you must always specify it as
|
|
|
|
/// a template parameter.
|
|
|
|
///
|
|
|
|
/// \code{.cpp}
|
2014-10-07 16:59:34 +00:00
|
|
|
/// vtkm::internal::FunctionInterface<void(vtkm::IdComponent,double,char)> functionInterface =
|
2014-06-06 21:20:50 +00:00
|
|
|
/// vtkm::internal::make_FunctionInterface<void>(1, 2.5, 'a');
|
|
|
|
/// \endcode
|
|
|
|
///
|
|
|
|
/// The number of parameters can be retrieved either with the constant field
|
|
|
|
/// \c ARITY or with the \c GetArity method.
|
|
|
|
///
|
|
|
|
/// \code{.cpp}
|
|
|
|
/// functionInterface.GetArity();
|
|
|
|
/// \endcode
|
|
|
|
///
|
2019-12-03 18:30:43 +00:00
|
|
|
/// You can get a particular parameter using the templated function \c
|
|
|
|
/// ParameterGet. The template parameter is the index of the parameter
|
|
|
|
/// (starting at 1).
|
2014-06-06 21:20:50 +00:00
|
|
|
///
|
2019-11-26 19:26:32 +00:00
|
|
|
/// Finally, there is a way to replace all of the parameters at
|
2014-06-06 21:20:50 +00:00
|
|
|
/// once. The \c StaticTransform methods take a transform functor that modifies
|
2019-11-26 19:26:32 +00:00
|
|
|
/// each of the parameters. See the documentation for this method for
|
|
|
|
/// details on how it is used.
|
2014-06-06 21:20:50 +00:00
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename FunctionSignature>
|
2014-04-10 19:35:06 +00:00
|
|
|
class FunctionInterface
|
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename OtherSignature>
|
2014-04-10 19:35:06 +00:00
|
|
|
friend class FunctionInterface;
|
|
|
|
|
|
|
|
public:
|
2018-02-22 13:29:13 +00:00
|
|
|
using Signature = FunctionSignature;
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2015-09-21 19:26:28 +00:00
|
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
2017-05-18 14:29:41 +00:00
|
|
|
FunctionInterface()
|
2019-11-26 19:26:32 +00:00
|
|
|
: Parameters()
|
2015-09-21 19:26:28 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-11-15 17:12:48 +00:00
|
|
|
VTKM_SUPPRESS_EXEC_WARNINGS
|
|
|
|
explicit FunctionInterface(const detail::ParameterContainer<FunctionSignature>& p)
|
2019-11-26 19:26:32 +00:00
|
|
|
: Parameters(p)
|
2017-11-15 17:12:48 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-08-01 16:37:55 +00:00
|
|
|
// the number of parameters as an integral constant
|
2018-02-22 13:29:13 +00:00
|
|
|
using SigInfo = detail::FunctionSigInfo<FunctionSignature>;
|
|
|
|
using ComponentSig = typename SigInfo::Components;
|
|
|
|
using ParameterSig = typename SigInfo::Parameters;
|
2016-04-19 20:04:53 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <vtkm::IdComponent ParameterIndex>
|
|
|
|
struct ParameterType
|
|
|
|
{
|
2018-02-22 13:29:13 +00:00
|
|
|
using type = typename detail::AtType<ParameterIndex, FunctionSignature>::type;
|
2014-04-10 19:35:06 +00:00
|
|
|
};
|
2016-04-19 20:04:53 +00:00
|
|
|
|
2014-04-10 19:35:06 +00:00
|
|
|
/// The number of parameters in this \c Function Interface.
|
|
|
|
///
|
2018-02-27 14:25:25 +00:00
|
|
|
static constexpr vtkm::IdComponent ARITY = SigInfo::Arity;
|
2014-04-10 19:35:06 +00:00
|
|
|
|
|
|
|
/// Returns the number of parameters held in this \c FunctionInterface. The
|
|
|
|
/// return value is the same as \c ARITY.
|
|
|
|
///
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC_CONT
|
2014-10-07 16:59:34 +00:00
|
|
|
vtkm::IdComponent GetArity() const { return ARITY; }
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Transform>
|
|
|
|
struct StaticTransformType
|
|
|
|
{
|
2018-02-22 13:29:13 +00:00
|
|
|
using type = FunctionInterface<
|
|
|
|
typename detail::FunctionInterfaceStaticTransformType<FunctionSignature, Transform>::type>;
|
2014-05-06 19:28:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Transforms the \c FunctionInterface based on compile-time
|
|
|
|
/// information.
|
|
|
|
///
|
2014-05-13 19:18:21 +00:00
|
|
|
/// The \c StaticTransform methods transform all the parameters of this \c
|
2014-05-06 19:28:08 +00:00
|
|
|
/// FunctionInterface to different types and values based on compile-time
|
2015-01-14 01:26:13 +00:00
|
|
|
/// information. It operates by accepting a functor that two arguments. The
|
|
|
|
/// first argument is the parameter to transform and the second argument is
|
|
|
|
/// an \c IndexTag specifying the index of the parameter (which can be
|
|
|
|
/// ignored in many cases). The functor's return value is the transformed
|
|
|
|
/// value. The functor must also contain a templated struct name ReturnType
|
|
|
|
/// with an internal type named \c type that defines the return type of the
|
|
|
|
/// transform for a given input type and parameter index.
|
2014-05-06 19:28:08 +00:00
|
|
|
///
|
|
|
|
/// The transformation is only applied to the parameters of the function. The
|
2014-11-10 18:04:05 +00:00
|
|
|
/// return argument is unaffected.
|
2014-05-06 19:28:08 +00:00
|
|
|
///
|
|
|
|
/// The return type can be determined with the \c StaticTransformType
|
|
|
|
/// template.
|
|
|
|
///
|
|
|
|
/// Here is an example of a transformation that converts a \c
|
|
|
|
/// FunctionInterface to another \c FunctionInterface containing pointers to
|
|
|
|
/// all of the parameters.
|
|
|
|
///
|
|
|
|
/// \code
|
|
|
|
/// struct MyTransformFunctor {
|
2015-01-14 01:26:13 +00:00
|
|
|
/// template<typename T, vtkm::IdComponent Index>
|
2014-05-06 19:28:08 +00:00
|
|
|
/// struct ReturnType {
|
|
|
|
/// typedef const T *type;
|
|
|
|
/// };
|
|
|
|
///
|
2015-01-14 01:26:13 +00:00
|
|
|
/// template<typename T, vtkm::IdComponent Index>
|
2016-10-19 22:42:58 +00:00
|
|
|
/// VTKM_CONT
|
2015-01-14 01:26:13 +00:00
|
|
|
/// const T *operator()(const T &x, vtkm::internal::IndexTag<Index>) const {
|
2014-05-06 19:28:08 +00:00
|
|
|
/// return &x;
|
|
|
|
/// }
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// template<typename FunctionSignature>
|
|
|
|
/// typename vtkm::internal::FunctionInterface<FunctionSignature>::template StaticTransformType<MyTransformFunctor>::type
|
|
|
|
/// ImportantStuff(const vtkm::internal::FunctionInterface<FunctionSignature> &funcInterface)
|
|
|
|
/// {
|
|
|
|
/// return funcInterface.StaticTransformCont(MyTransformFunctor());
|
|
|
|
/// }
|
|
|
|
/// \endcode
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Transform>
|
|
|
|
VTKM_CONT typename StaticTransformType<Transform>::type StaticTransformCont(
|
2018-07-02 18:28:58 +00:00
|
|
|
const Transform& transform)
|
2014-05-06 19:28:08 +00:00
|
|
|
{
|
2019-12-03 18:30:43 +00:00
|
|
|
using FuncIface = typename StaticTransformType<Transform>::type;
|
|
|
|
using PC = detail::ParameterContainer<typename FuncIface::Signature>;
|
|
|
|
return FuncIface{ detail::DoStaticTransformCont<PC>(transform, this->Parameters) };
|
2014-05-06 19:28:08 +00:00
|
|
|
}
|
2014-05-13 19:18:21 +00:00
|
|
|
|
2014-04-10 19:35:06 +00:00
|
|
|
detail::ParameterContainer<FunctionSignature> Parameters;
|
|
|
|
};
|
|
|
|
|
2019-12-03 18:30:43 +00:00
|
|
|
/// Gets the value for the parameter of the given index. Parameters are
|
|
|
|
/// indexed starting at 1. To use this method you have to specify a static,
|
|
|
|
/// compile time index.
|
|
|
|
///
|
|
|
|
/// \code{.cpp}
|
|
|
|
/// template<FunctionSignature>
|
|
|
|
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
|
|
|
|
/// {
|
|
|
|
/// bar( ParameterGet<2>(fInterface) );
|
|
|
|
/// }
|
|
|
|
/// \endcode
|
|
|
|
///
|
|
|
|
template <vtkm::IdComponent ParameterIndex, typename FunctionSignature>
|
|
|
|
VTKM_EXEC_CONT auto ParameterGet(const FunctionInterface<FunctionSignature>& fInterface)
|
|
|
|
-> decltype(detail::ParameterGet(fInterface.Parameters,
|
|
|
|
vtkm::internal::IndexTag<ParameterIndex>{}))
|
|
|
|
{
|
|
|
|
return detail::ParameterGet(fInterface.Parameters, vtkm::internal::IndexTag<ParameterIndex>{});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-26 19:26:32 +00:00
|
|
|
//============================================================================
|
|
|
|
/// \brief Create a \c FunctionInterface
|
|
|
|
///
|
|
|
|
/// \c make_FunctionInterface is a function that takes a variable number of
|
|
|
|
/// arguments and returns a \c FunctionInterface object containing these
|
|
|
|
/// objects. Since the return type for the function signature is not specified,
|
|
|
|
/// you must always specify it as a template parameter
|
|
|
|
///
|
|
|
|
/// \code{.cpp}
|
|
|
|
/// vtkm::internal::FunctionInterface<void(int,double,char)> functionInterface =
|
|
|
|
/// vtkm::internal::make_FunctionInterface<void>(1, 2.5, 'a');
|
|
|
|
/// \endcode
|
|
|
|
///
|
2014-04-10 19:35:06 +00:00
|
|
|
|
2019-11-26 19:26:32 +00:00
|
|
|
template <typename R, typename... Args>
|
|
|
|
FunctionInterface<R(Args...)> make_FunctionInterface(const Args&... args)
|
2014-04-10 19:35:06 +00:00
|
|
|
{
|
2020-07-14 17:35:46 +00:00
|
|
|
// MSVC will issue deprecation warnings if this templated method is instantiated with
|
|
|
|
// a deprecated class here even if the method is called from a section of code where
|
|
|
|
// deprecation warnings are suppressed. This is annoying behavior since this templated
|
|
|
|
// method has no control over what class it is used from. To get around it, we have to
|
|
|
|
// suppress all deprecation warnings here.
|
|
|
|
#ifdef VTKM_MSVC
|
|
|
|
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
|
|
|
#endif
|
2019-11-26 19:26:32 +00:00
|
|
|
detail::ParameterContainer<R(Args...)> container = { args... };
|
|
|
|
return FunctionInterface<R(Args...)>{ container };
|
2020-07-14 17:35:46 +00:00
|
|
|
#ifdef VTKM_MSVC
|
|
|
|
VTKM_DEPRECATED_SUPPRESS_END
|
|
|
|
#endif
|
2019-11-26 19:26:32 +00:00
|
|
|
}
|
2014-04-10 19:35:06 +00:00
|
|
|
}
|
|
|
|
} // namespace vtkm::internal
|
|
|
|
|
2014-06-25 22:03:44 +00:00
|
|
|
#include <vtkm/internal/FunctionInterfaceDetailPost.h>
|
|
|
|
|
2014-10-08 16:07:08 +00:00
|
|
|
#endif //vtk_m_internal_FunctionInterface_h
|