Reputation: 541
I tried to overload the operator- so that it applies set difference to its arguments. Since I couldn't figure out how to restrict it to STL containers only (because If I dont, it will overwriter every operator- it seems), I tried to restrict it to set and vector only, because I'd use it with those two. Here is my code:
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2,
class std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type>
T1 operator - (const T1 &l, const T2 &r)
{
assert(typeid(T1::value_type) == typeid(T2::value_type));
std::vector<T1::value_type> result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return T1(RANGE(result));
}
But when I try to compile my program i get the following errors:
Error 2 error C1903: unable to recover from previous error(s); stopping compilation C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
Error 1 error C2893: Failed to specialize function template 'unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const' C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm 3071 1 TrafficLight
I can't figure out the problem Im using VS2013
Best Regards Uzaku
Upvotes: 0
Views: 115
Reputation: 9602
There are a number of syntax errors with your code. The following example below works.
Note: The operator-
below is templated on T
instead of T1
and T2
because I wasn't sure you actually wanted to allow operator-
to work when using vectors of different types, e.g. std::vector<int>
and std::vector<double>
.
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T>
typename std::enable_if<is_STL_container<T>::value && is_STL_container<T>::value, T>::type
operator-(const T &l, const T &r)
{
T result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
1 5
Note: As pointed out in the comments by @StoryTeller, templating operator-
on just T
would prevent the valid usage of operator-
between std::vector<int>
and std::set<int>
(as attempted by the OP). The following code uses T1
and T2
to resolve this issue.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <set>
#include <typeinfo>
#include <vector>
#define RANGE(x) (x).begin(), (x).end()
template<class T>
struct is_STL_container
{
static const bool value = false;
};
template<class T, typename alloc>
struct is_STL_container<std::vector<T, alloc>>
{
static const bool value = true;
};
template<class T, class comp, typename alloc>
struct is_STL_container<std::set<T, comp, alloc>>
{
static const bool value = true;
};
template <class T1, class T2>
typename std::enable_if<is_STL_container<T1>::value && is_STL_container<T2>::value, T1>::type
operator-(const T1 &l, const T2 &r)
{
assert(typeid(typename T1::value_type) == typeid(typename T2::value_type));
T1 result;
std::set_difference(RANGE(l), RANGE(r), std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 2, 3, 4 };
std::set<int> c = { 2, 3, 4 };
std::vector<int> r = a - b;
for (const auto& v : r)
{
std::cout << v << " ";
}
std::cout << "\n";
r = a - c;
for (const auto& v : r)
{
std::cout << v << " ";
}
return 0;
}
1 5
1 5
Upvotes: 4
Reputation: 119847
Consider this definition
template <class T1, class T2, class int> int operator- ...
This is blatantly incorrect, right? But you have written only slightly more complicated version of it.
What you neef is
template <class T1, class T2>
typename std::enable_if<whatever>::type
operator- ...
Upvotes: 1
Reputation: 170065
std::enable_if
is a metafuction returning a type (defaulted to void).
As such, you main operator-
statement is malformed.
You must change the template class
parameter to look like this
class = typename std::enable_if_t<is_STL_container<T1>::value &&
is_STL_container<T2>::value>
Or this:
class = typename std::enable_if<is_STL_container<T1>::value &&
is_STL_container<T2>::value>::type
You can find the fixed program here.
Upvotes: 3