We've been bitten by the following bug many times:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(int* pn) { cout << *pn << " "; }
int main() {
int* n1 = new int(1);
int* n2 = new int(2);
int* n3 = new int(3);
vector<int*> v;
v.push_back(n1);
v.push_back(n2);
v.push_back(n3);
sort(v.begin(), v.end()); // Here be dragons!
for_each(v.begin(), v.end(), print);
cout << endl;
delete n1; delete n2; delete n3;
}
The problem is that std::sort is comparing integer pointers not integers, which is not what the programmer intended. Worse, the output may appear correct and deterministic (consider the order of addresses returned by new or allocated on the stack). The root problem is that sort eventually calls operator< for T, which is rarely a good idea when T is a pointer type.
Is there any way to prevent this or at least get a compiler warning? For example, is there a way to create a custom version of std::sort that requires a comparison function when T is a pointer?
IMO, the programmers should know that std::sort assumes the container stores values. If you need a different behavior for the comparison, then you provide a comparison function. E.g. (untested):
template<typename T>
inline bool deref_compare(T* t1, T* t2) { return *t1 < *t2; }
//...
std::sort(v.begin(), v.end(), deref_compare<int>);
Edit
FWIW, Jacob's answer comes closest to directly accomplishing what you want. There might be some ways to generalize it further.
For pointers in general you could do this:
#include <ctime>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <type_traits>
namespace util {
struct sort_pointers {
bool operator() ( int *a, int *b ) {
return *a < *b;
}
};
template <typename T, bool is_pointer = !std::tr1::is_pointer<T>::value>
struct sort_helper {
typedef std::less<T> wont_compare_pointers;
};
template <typename T>
struct sort_helper<T,false> {
};
template <typename Iterator>
void sort( Iterator start, Iterator end )
{
std::sort( start,
end,
sort_helper
<
typename Iterator::value_type
>::wont_compare_pointers() );
}
template <typename Iterator, class Func>
void sort( Iterator start, Iterator end, Func f ) {
std::sort( start, end, f );
}
}
int main() {
std::vector<int> v1;
std::vector<int*> v2;
srand(time(0));
for( int i = 0; i < 10; ++i ) {
v1.push_back(rand());
}
util::sort( v1.begin(), v1.end() );
for( int i = 0; i < 10; ++i ) {
v2.push_back(&v1[i]);
}
/* util::sort( v2.begin(), v2.end() ); */ //fails.
util::sort( v2.begin(), v2.end(), util::sort_pointers() );
return 0;
}
std::tr1::is_pointer was just what it was called in Visual Studio 2008, but I think Boost has one too, and newer compiles might provide it as std::is_pointer. I'm sure someone would be able to write a prettier solution, but this appears to work.
But I must say, I agree with cogwheel, there is no reason for this, the programmer should be able to see if this is going to be a problem and act accordingly.
Addition:
You can generalize it a bit more I think, to automatically select a functor that will dereference the pointers and compare the values:
namespace util {
template <typename T>
struct sort_pointers {
bool operator() ( T a, T b ) {
return *a < *b;
}
};
template <typename T, bool is_pointer = !std::tr1::is_pointer<T>::value>
struct sort_helper {
typedef std::less<T> compare;
};
template <typename T>
struct sort_helper<T,false> {
typedef sort_pointers<T> compare;
};
template <typename Iterator>
void sort( Iterator start, Iterator end )
{
std::sort( start,
end,
sort_helper
<
typename Iterator::value_type
>::compare() );
}
}
That way you don't have to think about if you're providing it with pointers to compare or not, it will automatically be sorted out.
I don't have a good answer for pointers in general, but you can restrict comparisons if you're using a smart pointer of any kind - eg boost::shared_ptr.
#include <boost/shared_ptr.hpp>
using namespace std;
template<class T>
bool operator<(boost::shared_ptr<T> a, boost::shared_ptr<T> b)
{
return boost::shared_ptr<T>::dont_compare_pointers;
}
int main () {
boost::shared_ptr<int> A;
boost::shared_ptr<int> B;
bool i = A < B;
}
Output:
In function 'bool operator<(boost::shared_ptr<T>, boost::shared_ptr<T>) [with T = int]':
t.cpp:15: instantiated from here
Line 8: error: 'dont_compare_pointers' is not a member of 'boost::shared_ptr<int>'
compilation terminated due to -Wfatal-errors.
So you can use smart pointers, or create your own smart pointer wrapper. This is very heavyweight for what you want though, so if you do create a wrapper to detect this situation, I recommend you only use it in debug mode. So create a macro (ugh, I know) and use it to declare pointers.
#ifdef DEBUG
#define pointer(x) pointer_wrapper<X>
#else
#define pointer(x) x*
#endif
This still requires your programmers to use it, of course!
Related
How can I wrap an OutputIterator such as back_inserter_iterator with a transformation?
Consider
std::vector<double> xx;
std::vector<double> yy;
std::vector<double> diff;
auto ba = std::back_inserter(diff);
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), ba);
I would like to apply a free function f(double) or g(std::vector<double>::iterator) before pushing back to the diff vector:
Specifically, how can I store the addresses of the diff elements (or iterators) instead of the elements themeselves.
std::vector<double&> diff;
auto baAdr = ??? std::back_inserter( ??? (diff));
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), baAdr);
For performance reasons (the real data is big) I do not want to construct a temporary vector and std::transform from it. It would also not work for non-copyable, movable types.
I can use boost.
With boost::function_output_iterator:
#include <vector>
#include <algorithm>
#include <boost/function_output_iterator.hpp>
int main()
{
std::vector<double> xx;
std::vector<double> yy;
std::vector<const double*> diff; // const pointers, or else you
// need a const_cast in lambda
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(),
boost::make_function_output_iterator(
[&diff](const double& d) { diff.push_back(&d); }
)
);
}
There's probably something built in to boost, but here's my hacky attempt to write my own iterator:
template <typename T, typename FN>
struct transform_iterator {
transform_iterator(T &t, FN fn)
: _t{t}
, _fn{std::move(fn)} { }
transform_iterator<T, FN>& operator * () { return *this; }
transform_iterator<T, FN>& operator ++ () { return *this; }
template <typename V>
transform_iterator<T, FN>& operator = (V const &v) {
_t.push_back(_fn(v));
return *this;
}
T &_t;
FN _fn;
};
This will take a function and execute it whenever something tries to assign to the iterator (I think this is how things like back_inserter usually work). A trivial helper function can create the iterators:
template <typename T, typename FN>
auto make_transform_iterator(T &t, FN fn) {
return transform_iterator<T, FN>{t, std::move(fn)};
};
Lastly, iterator_traits needs to be specialized so transform_iterator will work with algorithms.
namespace std {
template <typename T, typename FN>
struct iterator_traits<transform_iterator<T, FN>> {
using value_type = typename T::value_type;
};
}
There are more types that need to be set in iterator_traits, but this was sufficient for my testing; your mileage will vary.
My main looks like this:
int main() {
std::vector<int> xx{1, 2, 3};
std::vector<int> yy{1, 3, 5};
std::vector<int> diff;
auto ba = make_transform_iterator(diff, [](auto v) { return v + 10; });
std::set_difference(std::begin(xx), std::end(xx),
std::begin(yy), std::end(yy),
ba);
for(auto const &v: diff) {
std::cout << v << '\n';
}
return 0;
}
You could expand this to work with generic output iterators instead of just types that support push_back.
What's the use of value_type in STL containers?
From the MSDN:
// vector_value_type.cpp
// compile with: /EHsc
#include <vector>
#include <iostream>
int main( )
{
using namespace std;
vector<int>::value_type AnInt;
AnInt = 44;
cout << AnInt << endl;
}
I don't understand what does value_type achieve here?
The variable could be an int as well? Is it used because the coders are lazy to check what's the type of objects present in the vector?
I think these are also similar to it allocator_type,size_type,difference_type,reference,key_type etc..
Yes, in your example, it is pretty easy to know that you need an int. Where it gets complicated is generic programming. For example, if I wanted to write a generic sum() function, I would need it to know what kind of container to iterate and what type its elements are, so I would need to have something like this:
template<typename Container>
typename Container::value_type sum(const Container& cont)
{
typename Container::value_type total = 0;
for (const auto& e : cont)
total += e;
return total;
}
Essentially, I'm curious if you can use C++11 templates to make it so a templated function can detect an iterator's level of indirection and compile the function differently depending on that. For example, here is some code that won't compile:
#include <vector>
#include <list>
#include <type_traits>
#include <iostream>
struct MyStruct
{
int value;
MyStruct(int value = 42) : value(value) { }
const int& getInt() const { return value; }
};
typedef std::list<MyStruct> StructList;
typedef std::vector<const MyStruct*> StructPtrVector;
template <typename ITER_TYPE>
const int& getIteratorInt(ITER_TYPE iter)
{
if (std::is_pointer<decltype(*iter)>::value)
return (*iter)->getInt(); // Won't compile -> MyStruct has no operator-> defined
return iter->getInt(); // Won't compile -> MyStruct* has the wrong level of indirection
}
template <typename LIST_TYPE>
void PrintInts(const LIST_TYPE& intList)
{
for (auto iter = intList.begin(); iter != intList.end(); ++iter)
std::cout << getIteratorInt(iter) << std::endl;
}
int main(void)
{
StructList structList;
StructPtrVector structPtrs;
int values[5] = { 1, 4, 6, 4, 1 };
for (unsigned i = 0; i < 5; ++i)
{
structList.push_back(values[i]);
structPtrs.push_back(&structList.back());
}
PrintInts(structList);
PrintInts(structPtrs);
return 0;
}
The obvious situation is when you have a list of objects, and then a different kind of list of pointers to objects. And, what you want to do is the same to both lists, by treating them both as lists of objects.
The above code won't compile, because it is doing a logical check that should be done at compile-time. I don't know if there is a way to do this with preprocessor macros. I tried a simple #if std::is_pointer<decltype(*iter)>::value == true, but the compiler seems to always consider it false. (I've never tried preprocessor macros much before, but that is clearly not the proper way.)
Any idea if it's even possible?
When you want to select between two implementations depending on a metafunction such as is_pointer, use std::enable_if, which works on the principle of SFINAE.
template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
typename std::enable_if< std::is_pointer<
typename std::iterator_traits< ITER_TYPE >::value_type >::value,
const int& >::type
{
return (*iter)->getInt();
}
template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
typename std::enable_if< ! std::is_pointer<
typename std::iterator_traits< ITER_TYPE >::value_type >::value,
const int& >::type
{
return iter->getInt();
}
This way, template instantiation only sees lines of code that are valid for the given template arguments.
I've just applied this fix to your code mechanistically… I'm not advocating the use of multiple indirection or suggesting that the fixed implementation is robust.
I created an array template for my personal use.
template <typename T, int size>
struct Vector {
T data[size];
};
I tried to intialize the data like so:
Vector<unsigned char, 10> test;
test.data[] = {0,1,2,3,4,5,6,7,8,9};
My compiler ended up complaining something about "expected expression." Does anyone know what I'm doing? I want to be able to use this style of initialization where you give it the entire array definition at once instead of using a for loop to init the elements individually.
Since your class is an aggregate, you can initialize it with the usual brace syntax:
Vector<int, 3> x = { { 1, 2, 3 } };
The exact same thing applies to std::array<int, 3>.
In the new standard, C++11, you can use std::initalizer_list to get the desired result, see the below example.
#include <iostream>
#include <algorithm>
template <typename T, int size>
struct Vector {
T data[size];
Vector<T, size> (std::initializer_list<T> _data) {
std::copy (_data.begin (), _data.end (), data);
}
// ...
Vector<T, size>& operator= (std::initializer_list<T> const& _data) {
std::copy (_data.begin (), _data.end (), data);
return *this;
}
};
int
main (int argc, char *argv[])
{
Vector<int, 10> v ({1,2,3,4,5,6}); // std::initializer_list
v = {9,8,7,6,5,4,3,2,1,0}; // operator=
}
If you are working with a standard prior to C++11 it's a bit more of a hassle really, and your best bet is to implement functions similar to those available when using std::vector.
#include <iostream>
#include <algorithm>
template <typename T, int size>
struct Vector {
T _data[size];
Vector (T* begin, T* end) {
std::copy (begin, end, _data);
}
// ...
void assign (T* begin, T* end) {
std::copy (begin, end, _data);
}
};
int
main (int argc, char *argv[])
{
int A1[4] = {1,2,3,4};
int A2[5] = {99,88,77,66,55};
Vector<int, 10> v1 (A1, A1+4);
// ...
v1.assign (A2, A2+5);
}
You have to supply the type and size of the array when defining the variable:
Vector<int, 10> test;
You can not however assign to the member array like a normal array. You have to assign each element separately:
for (int i = 0; i < 10; i++)
test.data[i] = i; // If instantiated with type "int"
You can only initialize an array at the point you are defining it:
Vector<unsigned char, 10> test;
There's your array, you are done defining it, your chance to initialize it has passed.
Edit: Seeing Mat's answer, memo to me: I have to read up on C++11, and soon... :-/
Edit 2: I just gave the information on what was wrong. Kerrek SB has the information on how to do it right. ;-)
I have trouble describing my problem so I'll give an example:
I have a class description that has a couple of variables in it, for example:
class A{
float a, b, c, d;
}
Now, I maintain a vector<A> that contains many of these classes. What I need to do very very often is to find the object inside this vector that satisfies that one of it's parameters is maximal w.r.t to the others. i.e code looks something like:
int maxi=-1;
float maxa=-1000;
for(int i=0;i<vec.size();i++){
res= vec[i].a;
if(res > maxa) {
maxa= res;
maxi=i;
}
}
return vec[maxi];
However, sometimes I need to find class with maximal a, sometimes with maximal b, sometimes the class with maximal 0.8*a + 0.2*b, sometimes I want a maximal a*VAR + b, where VAR is some variable that is assigned in front, etc. In other words, I need to evaluate an expression for every class, and take the max. I find myself copy-pasting this everywhere, and only changing the single line that defines res.
Is there some nice way to avoid this insanity in C++? What's the neatest way to handle this?
Thank you!
I know this thread is old, but i find it quite useful to implement a powerful argmax function in C++.
However, as far as i can see, all the given examples above rely on std::max_element, which does comparison between the elements (either using a functor or by calling the operator<). this can be slow, if the calculation for each element is expensive. It works well for sorting numbers and handling simple classes, but what if the functor is much more complex? Maybe calculating a heuristic value of a chess position or something else that generate a huge tree etc.
A real argmax, as the thread starter mentioned, would only calculate its arg once, then save it to be compared with the others.
EDIT: Ok i got annoyed and had too much free time, so i created one < C++11 and one C++11 version with r-value references, first the C++11 version:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT && it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
template<typename IteratorT, typename HeuristicFunctorT>
inline IteratorT argmax(const IteratorT & begin, const IteratorT & end, const HeuristicFunctorT & functor) {
return argmax(IteratorT(begin), end, functor);
}
class IntPairFunctor : public std::unary_function< std::pair<int, int>, int > {
public:
int operator() (const std::pair<int, int> & v) const {
return v.first + v.second;
}
};
std::pair<int, int> rand_pair() {
return std::make_pair(rand(), rand());
}
int main(int argc, const char **argv) {
srand(time(NULL));
std::vector< std::pair<int, int> > ints;
std::generate_n(std::back_insert_iterator< std::vector< std::pair<int, int> > >(ints), 1000, rand_pair);
std::vector< std::pair<int, int> >::iterator m (argmax(ints.begin(), ints.end(), IntPairFunctor()));
std::cout << std::endl << "argmax: " << *m << std::endl;
}
The non C++11 version is much simpler, only the template:
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
Note that neither version requires any template arguments, the only requirement is that the heuristic implements the unary_function class
template <typename F>
struct CompareBy
{
bool operator()(const typename F::argument_type& x,
const typename F::argument_type& y)
{ return f(x) < f(y); }
CompareBy(const F& f) : f(f) {}
private:
F f;
};
template <typename T, typename U>
struct Member : std::unary_function<U, T>
{
Member(T U::*ptr) : ptr(ptr) {}
const T& operator()(const U& x) { return x.*ptr; }
private:
T U::*ptr;
};
template <typename F>
CompareBy<F> by(const F& f) { return CompareBy<F>(f); }
template <typename T, typename U>
Member<T, U> mem_ptr(T U::*ptr) { return Member<T, U>(ptr); }
You need to include <functional> for this to work. Now use, from header <algorithm>
std::max_element(v.begin(), v.end(), by(mem_ptr(&A::a)));
or
double combination(A x) { return 0.2 * x.a + 0.8 * x.b; }
and
std::max_element(v.begin(), v.end(), by(std::fun_ptr(combination)));
or even
struct combination : std::unary_function<A, double>
{
combination(double x, double y) : x(x), y(y) {}
double operator()(const A& u) { return x * u.a + y * u.b; }
private:
double x, y;
};
with
std::max_element(v.begin(), v.end(), by(combination(0.2, 0.8)));
to compare by a member or by linear combinations of a and b members. I split the comparer in two because the mem_ptr thing is damn useful and worth being reused. The return value of std::max_element is an iterator to the maximum value. You can dereference it to get the max element, or you can use std::distance(v.begin(), i) to find the corresponding index (include <iterator> first).
See http://codepad.org/XQTx0vql for the complete code.
This is what functors and STL are made for:
// A class whose objects perform custom comparisons
class my_comparator
{
public:
explicit my_comparator(float c1, float c2) : c1(c1), c2(c2) {}
// std::max_element calls this on pairs of elements
bool operator() (const A &x, const A &y) const
{
return (x.a*c1 + x.b*c2) < (y.a*c1 + y.b*c2);
}
private:
const float c1, c2;
};
// Returns the "max" element in vec
*std::max_element(vec.begin(), vec.end(), my_comparator(0.8,0.2));
Is the expression always linear? You could pass in an array of four coefficients. If you need to support arbitrary expressions, you'll need a functor, but if it's just an affine combination of the four fields then there's no need for all that complexity.
You can use the std::max_element algorithm with a custom comparator.
It's easy to write the comparator if your compiler supports lambda expressions.
If it doesn't, you can write a custom comparator functor. For the simple case of just comparing a single member, you can write a generic "member comparator" function object, which would look something like this:
template <typename MemberPointer>
struct member_comparator
{
MemberPointer p_;
member_comparator(MemberPointer p) : p_(p) { }
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
return lhs.*p_ < rhs.*p_;
}
};
template <typename MemberPointer>
member_comparator<MemberPointer> make_member_comparator(MemberPointer p)
{
return member_comparator<MemberPointer>(p);
}
used as:
// returns an iterator to the element that has the maximum 'd' member:
std::max_element(v.begin(), v.end(), make_member_comparator(&A::d));
You could use the std::max_element STL algorithm providing a custom comparison predicate each time.
With C++0x you can even use a lambda function for it for maximum conciseness:
auto maxElement=*std::max_element(vector.begin(), vector.end(), [](const A& Left, const A& Right) {
return (0.8*Left.a + 0.2*Left.b)<(0.8*Right.a + 0.2*Right.b);
});
Sample of using max_element/min_element with custom functor
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
struct A{
float a, b, c, d;
};
struct CompareA {
bool operator()(A const & Left, A const & Right) const {
return Left.a < Right.a;
}
};
int main() {
vector<A> vec;
vec.resize(3);
vec[0].a = 1;
vec[1].a = 2;
vec[2].a = 1.5;
vector<A>::iterator it = std::max_element(vec.begin(), vec.end(), CompareA());
cout << "Largest A: " << it->a << endl;
it = std::min_element(vec.begin(), vec.end(), CompareA());
cout << "Smallest A: " << it->a << endl;
}