Skip to content

Instantly share code, notes, and snippets.

@Psirus
Created July 14, 2017 08:41
Show Gist options
  • Save Psirus/b85a51a50d47ae32f24710e2abf5969e to your computer and use it in GitHub Desktop.
Save Psirus/b85a51a50d47ae32f24710e2abf5969e to your computer and use it in GitHub Desktop.
GroupRefactor
#pragma once
#include <algorithm>
#include <vector>
#include <boost/iterator/indirect_iterator.hpp>
namespace NuTo
{
namespace Groups
{
template <typename T>
class Group : private std::vector<T*>
{
public:
typedef std::vector<T*> parent;
typedef boost::indirect_iterator<typename parent::iterator> GroupIterator;
void AddMember(T& element)
{
parent::push_back(&element);
}
GroupIterator begin()
{
return parent::begin();
}
GroupIterator end()
{
return parent::end();
}
typename parent::iterator pbegin()
{
return parent::begin();
}
typename parent::iterator pend()
{
return parent::end();
}
typename parent::const_iterator pcbegin() const
{
return parent::cbegin();
}
typename parent::const_iterator pcend() const
{
return parent::cend();
}
bool Contains(const T& element)
{
auto result = std::find(parent::begin(), parent::end(), &element);
if (result != parent::end())
return true;
else
return false;
}
using parent::size;
using typename parent::iterator;
using typename parent::value_type;
using parent::insert;
};
template <typename T>
Group<T> Unite(const Group<T>& one, const Group<T>& two)
{
Group<T> newGroup;
std::insert_iterator<Group<T>> newGroupInsertIterator(newGroup, newGroup.pbegin());
std::set_union(one.pcbegin(), one.pcend(), two.pcbegin(), two.pcend(), newGroupInsertIterator);
return newGroup;
}
template <typename T>
Group<T> Difference(const Group<T>& one, const Group<T>& two)
{
Group<T> newGroup;
std::insert_iterator<Group<T>> newGroupInsertIterator(newGroup, newGroup.pbegin());
std::set_difference(one.pcbegin(), one.pcend(), two.pcbegin(), two.pcend(), newGroupInsertIterator);
return newGroup;
}
template <typename T>
Group<T> Intersection(const Group<T>& one, const Group<T>& two)
{
Group<T> newGroup;
std::insert_iterator<Group<T>> newGroupInsertIterator(newGroup, newGroup.pbegin());
std::set_intersection(one.pcbegin(), one.pcend(), two.pcbegin(), two.pcend(), newGroupInsertIterator);
return newGroup;
}
template <typename T>
Group<T> SymmetricDifference(const Group<T>& one, const Group<T>& two)
{
Group<T> newGroup;
std::insert_iterator<Group<T>> newGroupInsertIterator(newGroup, newGroup.pbegin());
std::set_symmetric_difference(one.pcbegin(), one.pcend(), two.pcbegin(), two.pcend(), newGroupInsertIterator);
return newGroup;
}
} // namespace Group
} // namespace NuTo
#include "BoostUnitTest.h"
#include "base/Group.h"
#include <iostream>
using namespace NuTo;
BOOST_AUTO_TEST_CASE(ContainsTest)
{
Groups::Group<int> group;
int a = 0;
BOOST_CHECK(not group.Contains(a));
group.AddMember(a);
BOOST_CHECK(group.Contains(a));
group.AddMember(a);
BOOST_CHECK(group.Contains(a));
}
class Foo
{
};
struct GroupTestFixture
{
GroupTestFixture()
{
groupOne.AddMember(a);
groupOne.AddMember(b);
groupOne.AddMember(c);
groupTwo.AddMember(c);
groupTwo.AddMember(d);
}
Foo a, b, c, d;
Groups::Group<Foo> groupOne;
Groups::Group<Foo> groupTwo;
};
BOOST_FIXTURE_TEST_CASE(unionTest, GroupTestFixture)
{
auto unionGroup = Groups::Unite(groupOne, groupTwo);
BOOST_CHECK_EQUAL(unionGroup.size(), 4);
BOOST_CHECK(unionGroup.Contains(a));
BOOST_CHECK(unionGroup.Contains(b));
BOOST_CHECK(unionGroup.Contains(c));
BOOST_CHECK(unionGroup.Contains(d));
}
BOOST_FIXTURE_TEST_CASE(differenceTest, GroupTestFixture)
{
auto diffGroup = Groups::Difference(groupOne, groupTwo);
BOOST_CHECK_EQUAL(diffGroup.size(), 2);
BOOST_CHECK(diffGroup.Contains(a));
BOOST_CHECK(diffGroup.Contains(b));
}
BOOST_FIXTURE_TEST_CASE(intersectionTest, GroupTestFixture)
{
auto intersectGroup = Groups::Intersection(groupOne, groupTwo);
BOOST_CHECK_EQUAL(intersectGroup.size(), 1);
BOOST_CHECK(intersectGroup.Contains(c));
}
BOOST_FIXTURE_TEST_CASE(symmetricDiffTest, GroupTestFixture)
{
auto symmetricDiffGroup = Groups::SymmetricDifference(groupOne, groupTwo);
BOOST_CHECK_EQUAL(symmetricDiffGroup.size(), 3);
BOOST_CHECK(symmetricDiffGroup.Contains(a));
BOOST_CHECK(symmetricDiffGroup.Contains(b));
BOOST_CHECK(symmetricDiffGroup.Contains(d));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment