Commit 0846f1a8 authored by Julien Michel's avatar Julien Michel

DOC: add documentation (WIP)

parent 6eb7f0ca
//--------------------------------------
// utils/traits: Additional type traits
//--------------------------------------
//
// Copyright kennytm (auraHT Ltd.) 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file doc/LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
/**
``<utils/traits.hpp>`` --- Additional type traits
=================================================
This module provides additional type traits and related functions, missing from
the standard library.
*/
#ifndef TRAITS_HPP_9ALQFEFX7TO
#define TRAITS_HPP_9ALQFEFX7TO 1
#include <cstdlib>
#include <tuple>
#include <functional>
#include <type_traits>
namespace FunctionTraits {
/**
.. macro:: DECLARE_HAS_TYPE_MEMBER(member_name)
This macro declares a template ``has_member_name`` which will check whether
a type member ``member_name`` exists in a particular type.
Example::
DECLARE_HAS_TYPE_MEMBER(result_type)
...
printf("%d\n", has_result_type< std::plus<int> >::value);
// ^ prints '1' (true)
printf("%d\n", has_result_type< double(*)() >::value);
// ^ prints '0' (false)
*/
#define DECLARE_HAS_TYPE_MEMBER(member_name) \
template <typename, typename = void> \
struct has_##member_name \
{ enum { value = false }; }; \
template <typename T> \
struct has_##member_name<T, typename std::enable_if<sizeof(typename T::member_name)||true>::type> \
{ enum { value = true }; };
/**
.. type:: struct utils::function_traits<F>
Obtain compile-time information about a function object *F*.
This template currently supports the following types:
* Normal function types (``R(T...)``), function pointers (``R(*)(T...)``)
and function references (``R(&)(T...)`` and ``R(&&)(T...)``).
* Member functions (``R(C::*)(T...)``)
* ``std::function<F>``
* Type of lambda functions, and any other types that has a unique
``operator()``.
* Type of ``std::mem_fn`` (only for GCC's libstdc++ and LLVM's libc++).
Following the C++ spec, the first argument will be a raw pointer.
*/
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
namespace xx_impl
{
template <typename C, typename R, typename... A>
struct memfn_type
{
typedef typename std::conditional<
std::is_const<C>::value,
typename std::conditional<
std::is_volatile<C>::value,
R (C::*)(A...) const volatile,
R (C::*)(A...) const
>::type,
typename std::conditional<
std::is_volatile<C>::value,
R (C::*)(A...) volatile,
R (C::*)(A...)
>::type
>::type type;
};
}
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType(Args...)>
{
/**
.. type:: type result_type
The type returned by calling an instance of the function object type *F*.
*/
typedef ReturnType result_type;
/**
.. type:: type function_type
The function type (``R(T...)``).
*/
typedef ReturnType function_type(Args...);
/**
.. type:: type member_function_type<OwnerType>
The member function type for an *OwnerType* (``R(OwnerType::*)(T...)``).
*/
template <typename OwnerType>
using member_function_type = typename xx_impl::memfn_type<
typename std::remove_pointer<typename std::remove_reference<OwnerType>::type>::type,
ReturnType, Args...
>::type;
/**
.. data:: static const size_t arity
Number of arguments the function object will take.
*/
enum { arity = sizeof...(Args) };
/**
.. type:: type arg<n>::type
The type of the *n*-th argument.
*/
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType(*)(Args...)>
: public function_traits<ReturnType(Args...)>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...)>
: public function_traits<ReturnType(Args...)>
{
typedef ClassType& owner_type;
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
: public function_traits<ReturnType(Args...)>
{
typedef const ClassType& owner_type;
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) volatile>
: public function_traits<ReturnType(Args...)>
{
typedef volatile ClassType& owner_type;
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const volatile>
: public function_traits<ReturnType(Args...)>
{
typedef const volatile ClassType& owner_type;
};
template <typename FunctionType>
struct function_traits<std::function<FunctionType>>
: public function_traits<FunctionType>
{};
#if defined(_GLIBCXX_FUNCTIONAL)
#define MEM_FN_SYMBOL_XX0SL7G4Z0J std::_Mem_fn
#elif defined(_LIBCPP_FUNCTIONAL)
#define MEM_FN_SYMBOL_XX0SL7G4Z0J std::__mem_fn
#endif
#ifdef MEM_FN_SYMBOL_XX0SL7G4Z0J
template <typename R, typename C>
struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R C::*>>
: public function_traits<R(C*)>
{};
template <typename R, typename C, typename... A>
struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...)>>
: public function_traits<R(C*, A...)>
{};
template <typename R, typename C, typename... A>
struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) const>>
: public function_traits<R(const C*, A...)>
{};
template <typename R, typename C, typename... A>
struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) volatile>>
: public function_traits<R(volatile C*, A...)>
{};
template <typename R, typename C, typename... A>
struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) const volatile>>
: public function_traits<R(const volatile C*, A...)>
{};
#undef MEM_FN_SYMBOL_XX0SL7G4Z0J
#endif
template <typename T>
struct function_traits<T&> : public function_traits<T> {};
template <typename T>
struct function_traits<const T&> : public function_traits<T> {};
template <typename T>
struct function_traits<volatile T&> : public function_traits<T> {};
template <typename T>
struct function_traits<const volatile T&> : public function_traits<T> {};
template <typename T>
struct function_traits<T&&> : public function_traits<T> {};
template <typename T>
struct function_traits<const T&&> : public function_traits<T> {};
template <typename T>
struct function_traits<volatile T&&> : public function_traits<T> {};
template <typename T>
struct function_traits<const volatile T&&> : public function_traits<T> {};
#define FORWARD_RES_8QR485JMSBT \
typename std::conditional< \
std::is_lvalue_reference<R>::value, \
T&, \
typename std::remove_reference<T>::type&& \
>::type
/**
.. function:: auto utils::forward_like<Like, T>(T&& t) noexcept
Forward the reference *t* like the type of *Like*. That means, if *Like* is
an lvalue (reference), this function will return an lvalue reference of *t*.
Otherwise, if *Like* is an rvalue, this function will return an rvalue
reference of *t*.
This is mainly used to propagate the expression category (lvalue/rvalue) of
a member of *Like*, generalizing ``std::forward``.
*/
template <typename R, typename T>
FORWARD_RES_8QR485JMSBT forward_like(T&& input) noexcept
{
return static_cast<FORWARD_RES_8QR485JMSBT>(input);
}
#undef FORWARD_RES_8QR485JMSBT
/**
.. type:: struct utils::copy_cv<From, To>
Copy the CV qualifier between the two types. For example,
``utils::copy_cv<const int, double>::type`` will become ``const double``.
*/
template <typename From, typename To>
struct copy_cv
{
private:
typedef typename std::remove_cv<To>::type raw_To;
typedef typename std::conditional<std::is_const<From>::value,
const raw_To, raw_To>::type const_raw_To;
public:
/**
.. type:: type type
Result of cv-copying.
*/
typedef typename std::conditional<std::is_volatile<From>::value,
volatile const_raw_To, const_raw_To>::type type;
};
/**
.. type:: struct utils::pointee<T>
Returns the type by derefering an instance of *T*. This is a generalization
of ``std::remove_pointer``, that it also works with iterators.
*/
template <typename T>
struct pointee
{
/**
.. type:: type type
Result of dereferencing.
*/
typedef typename std::remove_reference<decltype(*std::declval<T>())>::type type;
};
/**
.. function:: std::add_rvalue_reference<T>::type utils::rt_val<T>() noexcept
Returns a value of type *T*. It is guaranteed to do nothing and will not
throw a compile-time error, but using the returned result will cause
undefined behavior.
*/
template <typename T>
typename std::add_rvalue_reference<T>::type rt_val() noexcept
{
return std::move(*static_cast<T*>(nullptr));
}
}
#endif
......@@ -22,11 +22,164 @@
#define otbFunctorImageFilter_hxx
#include "otbFunctorImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkDefaultConvertPixelTraits.h"
namespace otb
{
namespace functor_filter_details
{
// Variadic SetRequestedRegion
// This function sets the requested region for one image
template<class T> int SetInputRequestedRegion(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
{
auto currentRegion = region;
currentRegion.PadByRadius(radius);
// The ugly cast in all ITK filters
T * nonConstImg = const_cast<T*>(img);
if(currentRegion.Crop(img->GetLargestPossibleRegion()))
{
nonConstImg->SetRequestedRegion(currentRegion);
return 0;
}
else
{
nonConstImg->SetRequestedRegion(currentRegion);
// build an exception
itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
std::ostringstream msg;
msg << "::SetInputRequestedRegion<>()";
e.SetLocation(msg.str());
e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
e.SetDataObject(nonConstImg);
throw e;
}
return 0;
}
template <class Tuple, size_t...Is> auto SetInputRequestedRegionsImpl(Tuple & t, const itk::ImageRegion<2> & region, std::index_sequence<Is...>,const itk::Size<2> & radius)
{
return std::make_tuple(SetInputRequestedRegion(std::get<Is>(t),region,radius)...);
}
template <typename... T> auto SetInputRequestedRegions(std::tuple<T...> && t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius)
{
return SetInputRequestedRegionsImpl(t,region,std::make_index_sequence<sizeof...(T)>{},radius);
}
template <class Tuple, size_t...Is> auto GetNumberOfComponentsPerInputImpl(Tuple & t, std::index_sequence<Is...>)
{
return std::array<size_t,sizeof...(Is)>{{std::get<Is>(t)->GetNumberOfComponentsPerPixel()...}};
}
template <typename ...T> auto GetNumberOfComponentsPerInput(std::tuple<T...> & t)
{
return GetNumberOfComponentsPerInputImpl(t, std::make_index_sequence<sizeof...(T)>{});
}
template <typename N> struct MakeIterator {};
template <> struct MakeIterator<std::false_type>
{
template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>&)
{
itk::ImageRegionConstIterator<T> it(img,region);
return it;
}
};
template <> struct MakeIterator<std::true_type>
{
template <class T> static auto Make(const T * img, const itk::ImageRegion<2> & region, const itk::Size<2>& radius)
{
itk::ConstNeighborhoodIterator<T> it(radius,img,region);
return it;
}
};
template <class TNeigh, class Tuple, size_t...Is> auto MakeIteratorsImpl(const Tuple& t, const itk::ImageRegion<2> & region, const itk::Size<2> & radius, std::index_sequence<Is...>, TNeigh)
{
return std::make_tuple(MakeIterator<typename std::tuple_element<Is,TNeigh>::type >::Make(std::get<Is>(t),region,radius)...);
}
template<class TNeigh, typename... T> auto MakeIterators(std::tuple<T...> &&t,const itk::ImageRegion<2> & region, const itk::Size<2> & radius, TNeigh n)
{
return MakeIteratorsImpl(t,region,radius,std::make_index_sequence<sizeof...(T)>{},n);
}
// Variadic call of operator from iterator tuple
template <typename T> struct GetProxy{};
template <typename T> struct GetProxy<itk::ImageRegionConstIterator<T> >
{
static auto Get(const itk::ImageRegionConstIterator<T> & t)
{
return t.Get();
}
};
template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
{
static auto Get(const itk::ConstNeighborhoodIterator<T> & t)
{
return t.GetNeighborhood();
}
};
template <class Tuple, class Oper, size_t...Is> auto CallOperatorImpl(Tuple& t, const Oper & oper,std::index_sequence<Is...>)
{
return oper(GetProxy<typename std::remove_reference<decltype(std::get<Is>(t))>::type>::Get(std::get<Is>(t))...);
}
template <class Oper, typename ... Args> auto CallOperator(const Oper& oper, std::tuple<Args...> & t)
{
return CallOperatorImpl(t,oper,std::make_index_sequence<sizeof...(Args)>{});
}
// Variadic move of iterators
template<class Tuple,size_t...Is> auto MoveIteratorsImpl(Tuple & t, std::index_sequence<Is...>)
{
return std::make_tuple(++(std::get<Is>(t) )...);
}
template<typename ... Args> void MoveIterators(std::tuple<Args...> & t)
{
MoveIteratorsImpl(t,std::make_index_sequence<sizeof...(Args)>{});
}
// Default implementation does nothing
template <class F, class O, size_t N> struct NumberOfOutputComponents
{};
template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::Image<T>,N>
{
// We can not be here if output type is VectorImage
static void Set(const F&, otb::Image<T> *, std::array<size_t,N>){}
};
// O is a VectorImage AND F has a fixed OuptutSize static constexrp size_t;
template <class F, class T, size_t N> struct NumberOfOutputComponents<F,otb::VectorImage<T>,N>
{
static void Set(const F & f, otb::VectorImage<T> * outputImage, std::array<size_t,N> inNbBands)
{
outputImage->SetNumberOfComponentsPerPixel(f.OutputSize(inNbBands));
}
};
} // end namespace functor_filter_details
template <class TFunction>
FunctorImageFilter<TFunction>::FunctorImageFilter()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment