Reputation: 21793
No C++11 or Boost :(
I have a function with the following signature.
template<class INPUT_ITR, class OUTPUT_ITR>
void DoWork(const INPUT_ITR in_it, const INPUT_ITR in_it_end, OUTPUT_ITR out_it, OUTPUT_ITR out_it_end, CONTEXT_DATA)
Normally some complex processing takes place between the input and output.. but sometimes a no-op is required, and the data is simply copied. The function supports in-place operations if the input and output data types are the same. So I have this code.
if (NoOp)
{
if (in_it != out_it)
{
copy(in_it, in_it_end, out_it);
}
}
If an in-place operation has been requested (the iterator check), there is no need to copy any data.
This has worked fine until I call the function with iterators to different data types (int32 to int64 for example). Then it complains about the iterator check because they are incompatible types.
error C2679: binary '!=' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned __int64>>>
This has left me a bit stumped. Is there an easy way to perform this check if the data types are the same, but simply perform the copy if they are different types?
Thanks
Upvotes: 1
Views: 170
Reputation: 254531
You can extract the test into a pair of templates; one for matching types, one for non-matching types.
template <class T1, class T2>
bool same(T1 const &, T2 const &) {return false;}
template <class T>
bool same(T const & a, T const & b) {return a == b;}
Beware that this can give confusing results when used with types that you'd expect to be comparable. In C++11 (or with Boost, or a lot of tedious mucking around with templates) you could extend this to compare different types when possible; but that's beyond what you need here.
Also, note that you're relying on formally undefined behaviour, since iterators over different underlying sequences aren't required to be comparable. There is no way to tell from the iterators themselves whether this is the case.
Upvotes: 4
Reputation: 52365
You could use std::iterator_traits
and a custom is_same
type trait since you don't have c++11:
template<class T, class U>
struct is_same
{
static const bool value = false;
};
template<class T>
struct is_same<T, T>
{
static const bool value = true;
};
if(!is_same<typename std::iterator_traits<INPUT_ITR>::value_type,
typename std::iterator_traits<OUTPUT_ITR>::value_type>::value)
{
copy(...);
}
Upvotes: 0
Reputation: 21793
I came up with a workaround. Any better suggestions welcome.
Overload the function to provide an in-place version. It's up to the user to request in-place now (in-place using the old function will perform the redundant copy in case of no op).
template<class ITR>
void DoWork(const ITR it, const ITR it_end, CONTEXT_DATA)
{
if (! NoOp)
{
DoWork(it, it_end, it, it_end, sSourceSpec, sDestSpec);
}
}
Upvotes: 1