#ifndef CONDITIONAL_FORWARD_HPP_
#define CONDITIONAL_FORWARD_HPP_
#include <type_traits>
namespace datasketches {
template<typename T1, typename T2>
using fwd_type = typename std::conditional<std::is_lvalue_reference<T1>::value,
T2, typename std::remove_reference<T2>::type&&>::type;
template<typename T1, typename T2>
fwd_type<T1, T2> conditional_forward(T2&& value) {
return std::forward<fwd_type<T1, T2>>(std::forward<T2>(value));
}
template<typename Container>
auto forward_begin(Container&& c) -> typename std::enable_if<
std::is_lvalue_reference<Container>::value ||
std::is_same<typename std::remove_reference<Container>::type::const_iterator, decltype(c.begin())>::value,
decltype(c.begin())
>::type
{
return c.begin();
}
template<typename Container>
auto forward_begin(Container&& c) -> typename std::enable_if<
!std::is_lvalue_reference<Container>::value &&
!std::is_same<typename std::remove_reference<Container>::type::const_iterator, decltype(c.begin())>::value,
decltype(std::make_move_iterator(c.begin()))
>::type
{
return std::make_move_iterator(c.begin());
}
template<typename Container>
auto forward_end(Container&& c) -> typename std::enable_if<
std::is_lvalue_reference<Container>::value ||
std::is_same<typename std::remove_reference<Container>::type::const_iterator, decltype(c.begin())>::value,
decltype(c.end())
>::type
{
return c.end();
}
template<typename Container>
auto forward_end(Container&& c) -> typename std::enable_if<
!std::is_lvalue_reference<Container>::value &&
!std::is_same<typename std::remove_reference<Container>::type::const_iterator, decltype(c.begin())>::value,
decltype(std::make_move_iterator(c.end()))
>::type
{
return std::make_move_iterator(c.end());
}
}
#endif