Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to C++ MakePath/MakePathD #401

Merged
merged 1 commit into from
Feb 6, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 58 additions & 25 deletions CPP/Clipper2Lib/include/clipper2/clipper.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,44 +503,77 @@ namespace Clipper2Lib {
return true;
}

namespace details {

template<typename T, typename U>
inline constexpr void MakePathGeneric(const T list, size_t size,
std::vector<U>& result)
{
for (size_t i = 0; i < size; ++i)
#ifdef USINGZ
result[i / 2] = U{list[i], list[++i], 0};
#else
result[i / 2] = U{list[i], list[++i]};
#endif
}

} // end details namespace

template<typename T,
typename std::enable_if<
std::is_integral<T>::value &&
!std::is_same<char, T>::value, bool
>::type = true>
inline Path64 MakePath(const std::vector<T>& list)
{
const auto size = list.size() - list.size() % 2;
if (list.size() != size)
DoError(non_pair_error_i); // non-fatal without exception handling
Path64 result(size / 2); // else ignores unpaired value
details::MakePathGeneric(list, size, result);
return result;
}

template<typename T, std::size_t N,
typename std::enable_if<
std::is_integral<T>::value &&
!std::is_same<char, T>::value, bool
>::type = true>
inline Path64 MakePath(const T(&list)[N])
{
if (N % 2 != 0)
// Make the compiler error on unpaired value (i.e. no runtime effects).
static_assert(N % 2 == 0, "MakePath requires an even number of arguments");
Path64 result(N / 2);
details::MakePathGeneric(list, N, result);
return result;
}

template<typename T,
typename std::enable_if<
std::is_arithmetic<T>::value &&
!std::is_same<char, T>::value, bool
>::type = true>
inline PathD MakePathD(const std::vector<T>& list)
{
const auto size = list.size() - list.size() % 2;
if (list.size() != size)
DoError(non_pair_error_i); // non-fatal without exception handling
Path64 result; // else ignores unpaired value
result.reserve(N / 2);
#ifdef USINGZ
for (size_t i = 0; i < N; ++i)
result.emplace_back(Point64{ list[i], list[++i], 0 });
#else
for (size_t i = 0; i < N; ++i)
result.emplace_back(Point64{ list[i], list[++i] });
#endif
PathD result(size / 2); // else ignores unpaired value
details::MakePathGeneric(list, size, result);
return result;
}

template<typename T, std::size_t N,
typename std::enable_if<std::is_arithmetic<T>::value &&
!std::is_same<char, T>::value, bool
>::type = true>
typename std::enable_if<
std::is_arithmetic<T>::value &&
!std::is_same<char, T>::value, bool
>::type = true>
inline PathD MakePathD(const T(&list)[N])
{
if (N % 2 != 0)
DoError(non_pair_error_i); // non-fatal without exception handling
PathD result; // else ignores unpaired value
result.reserve(N / 2);
#ifdef USINGZ
for (size_t i = 0; i < N; ++i)
result.emplace_back(PointD{ list[i], list[++i], 0 });
#else
for (size_t i = 0; i < N; ++i)
result.emplace_back(PointD{ list[i], list[++i] });
#endif
// Make the compiler error on unpaired value (i.e. no runtime effects).
static_assert(N % 2 == 0, "MakePath requires an even number of arguments");
PathD result(N / 2);
details::MakePathGeneric(list, N, result);
return result;
}

Expand Down