Fixed compatibility with old compilers

This commit is contained in:
Alexander Zaitsev
2017-07-19 02:15:06 +03:00
parent e07e8e65c6
commit 15c7ff3828
3 changed files with 72 additions and 26 deletions

View File

@ -18,6 +18,7 @@ namespace ba = boost::algorithm;
int main ( int /*argc*/, char * /*argv*/ [] )
{
// WARNING: Example require C++11 or newer compiler
{
std::cout << "apply_permutation with iterators:\n";
std::vector<int> vec{1, 2, 3, 4, 5}, order{4, 2, 3, 1, 0};

View File

@ -19,7 +19,7 @@
#define BOOST_ALGORITHM_APPLY_PERMUTATION_HPP
#include <algorithm>
#include <type_traits>
#include <iterator>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
@ -41,14 +41,14 @@ void
apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end,
RandomAccessIterator2 ind_begin)
{
using Diff = typename std::iterator_traits<RandomAccessIterator1>::difference_type;
typedef typename std::iterator_traits<RandomAccessIterator1>::difference_type Diff;
Diff size = std::distance(item_begin, item_end);
for (Diff i = 0; i < size; i++)
for (Diff i = 0; i < size; ++i)
{
auto current = i;
Diff current = i;
while (i != ind_begin[current])
{
auto next = ind_begin[current];
Diff next = static_cast<Diff>(ind_begin[current]);
std::swap(item_begin[current], item_begin[next]);
ind_begin[current] = current;
current = next;
@ -68,14 +68,12 @@ apply_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_e
/// Complexity: O(N).
template<typename RandomAccessIterator1, typename RandomAccessIterator2>
void
apply_reverse_permutation(
RandomAccessIterator1 item_begin,
RandomAccessIterator1 item_end,
apply_reverse_permutation(RandomAccessIterator1 item_begin, RandomAccessIterator1 item_end,
RandomAccessIterator2 ind_begin)
{
using Diff = typename std::iterator_traits<RandomAccessIterator2>::difference_type;
typedef typename std::iterator_traits<RandomAccessIterator1>::difference_type Diff;
Diff length = std::distance(item_begin, item_end);
for (Diff i = 0; i < length; i++)
for (Diff i = 0; i < length; ++i)
{
while (i != ind_begin[i])
{

View File

@ -9,13 +9,10 @@
*/
#include <vector>
#include <list>
#include <iterator>
#include <functional>
#include <iostream>
#include <boost/algorithm/apply_permutation.hpp>
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
@ -28,42 +25,67 @@ void test_apply_permutation()
//Empty
{
std::vector<int> vec, order, result;
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//1 element
{
std::vector<int> vec{1}, order{0}, result{1};
std::vector<int> vec, order, result;
vec.push_back(1);
order.push_back(0);
result = vec;
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//2 elements, no changes
{
std::vector<int> vec{1, 2}, order{0, 1}, result{1, 2};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2);
order.push_back(0); order.push_back(1);
result = vec;
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//2 elements, changed
{
std::vector<int> vec{1, 2}, order{1, 0}, result{2, 1};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2);
order.push_back(1); order.push_back(0);
result.push_back(2); result.push_back(1);
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Multiple elements, no changes
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4);
result = vec;
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Multiple elements, changed
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0);
result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1);
ba::apply_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Just test range interface
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4);
result = vec;
ba::apply_permutation(vec, order);
BOOST_CHECK(vec == result);
}
@ -74,42 +96,67 @@ void test_apply_reverse_permutation()
//Empty
{
std::vector<int> vec, order, result;
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//1 element
{
std::vector<int> vec{1}, order{0}, result{1};
std::vector<int> vec, order, result;
vec.push_back(1);
order.push_back(0);
result = vec;
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//2 elements, no changes
{
std::vector<int> vec{1, 2}, order{0, 1}, result{1, 2};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2);
order.push_back(0); order.push_back(1);
result = vec;
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//2 elements, changed
{
std::vector<int> vec{1, 2}, order{1, 0}, result{2, 1};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2);
order.push_back(1); order.push_back(0);
result.push_back(2); result.push_back(1);
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Multiple elements, no changes
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4);
result = vec;
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Multiple elements, changed
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{4, 3, 2, 1, 0}, result{5, 4, 3, 2, 1};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(4); order.push_back(3); order.push_back(2); order.push_back(1); order.push_back(0);
result.push_back(5); result.push_back(4); result.push_back(3); result.push_back(2); result.push_back(1);
ba::apply_reverse_permutation(vec.begin(), vec.end(), order.begin());
BOOST_CHECK(vec == result);
}
//Just test range interface
{
std::vector<int> vec{1, 2, 3, 4, 5}, order{0, 1, 2, 3, 4}, result{1, 2, 3, 4, 5};
std::vector<int> vec, order, result;
vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5);
order.push_back(0); order.push_back(1); order.push_back(2); order.push_back(3); order.push_back(4);
result = vec;
ba::apply_reverse_permutation(vec, order);
BOOST_CHECK(vec == result);
}