Run-time dynamic sort ordering

Started by
23 comments, last by rozz666 15 years, 10 months ago
So we have to wait for C++0x rvalue references or try this:

#include <algorithm>#include <iostream>#include <vector>#include <functional>struct Comp : public std::binary_function<int, int, bool>{    Comp() {}    Comp(const Comp& old) { std::cout << "copy constructor" << std::endl; }    bool operator () (int lhs, int rhs) const { return lhs < rhs; }};template <typename Fn2>class binary_function_ref    : public std::binary_function<typename Fn2::first_argument_type,                                  typename Fn2::second_argument_type,                                  typename Fn2::result_type> {public:    explicit binary_function_ref(const Fn2& fn2) : fn2(fn2) { }    typename Fn2::result_type operator()(const typename Fn2::first_argument_type& arg1, typename Fn2::second_argument_type& arg2)    {        return fn2(arg1, arg2);    }private:    const Fn2& fn2;};template <typename Fn2>binary_function_ref<Fn2> make_ref(const Fn2& fn2){    return binary_function_ref<Fn2>(fn2);}int main(int argc, char** argv){    std::vector<int> big;    for (int i = 1000; i; --i) big.push_back(i);    std::sort(big.begin(), big.end(), make_ref(Comp()));    return 1;}


[Edited by - rozz666 on June 26, 2008 9:29:49 AM]
Advertisement
Quote:Original post by rozz666
So we have to wait for C++0x rvalue references or try this:



That's pretty much what I did with the internal 'Holder' class in my original post :]

I'm curious how your solution could be expanded to accept accessors as well as regular members. I tried adding:

template <typename T, typename M, M (T::*member)() const>class order_pred{    public:        static bool before(const T& left, const T& right)        {            return (left.*member)() < (right.*member)();        }};template <typename M, M (T:: *m)() const>ordered_comparator& add(){    preds.push_back(order_pred<T, M, m>::before);    return (*this);}


... but this seems to confuse the compiler. It doesn't seem to be able to distinguish between M (T:: *m)() const and M const T:: *m.

[Edited by - godecho on June 26, 2008 11:40:17 AM]
Quote:Original post by godecho
Quote:Original post by rozz666
So we have to wait for C++0x rvalue references or try this:



That's pretty much what I did with the internal 'Holder' class in my original post :]

I'm curious how your solution could be expanded to accept accessors as well as regular members. I tried adding:

template <typename T, typename M, M (T::*member)() const>class order_pred{    public:        static bool before(const T& left, const T& right)        {            return (left.*member)() < (right.*member)();        }};template <typename M, M (T:: *m)() const>ordered_comparator& add(){    preds.push_back(order_pred<T, M, m>::before);    return (*this);}


... but this seems to confuse the compiler. It doesn't seem to be able to distinguish between M (T:: *m)() const and M const T:: *m.


It works on my compiler (Borland Turbo C++). Try template <typename T, typename M, M ((T:: *member)() const)>.
Don't remove the ability to compare member variables. Define additional structures instead.
template <typename T, typename M, M (T:: *member)() const>class order_func_pred {public:    static bool before(const T& left, const T& right)    {        return (left.*member)() < (right.*member)();    }};//...    template <typename M, M (T:: *f)() const>    void add()    {        preds.push_back(order_func_pred<T, M, f>::before);    }//...
Quote:Original post by rozz666
It works on my compiler (Borland Turbo C++). Try template <typename T, typename M, M ((T:: *member)() const)>.
Don't remove the ability to compare member variables. Define additional structures instead.


I didn't remove the old functions, I added new ones so that member variables could still be compared. That's where the problem is though... the addition of those extra structures confuses vc++8:

struct Foo{    int a, b;    int getB() const { return b; }};template <class T> struct Bar{    template <class M, M  T::* m>          void add() { /* do something with member_ptr */ }    template <class M, M (T::* m)() const> void add() { /* do something with member_function_ptr*/ }};int main(int argc, char** argv){    Bar<Foo> bar;    bar.add<int, &Foo::a>();    bar.add<int, &Foo::getB>();    return 1;}


which gives the error message:
error C2440: 'specialization' : cannot convert from 'int Foo::* ' to 'int (__thiscall Foo::* const )(void) const' There is no context in which this conversion is possibleerror C2973: 'Bar<T>::add' : invalid template argument 'int Foo::* '  with [ T=Foo ] see declaration of 'Bar<T>::add' with [ T=Foo ]error C2668: 'Bar<T>::add' : ambiguous call to overloaded function with [ T=Foo ]    could be 'void Bar<T>::add<int,pointer-to-member(0x0)>(void)' with [ T=Foo ]    or 'void Bar<T>::add<int,pointer-to-member(0x0)>(void)' with [ T=Foo ]    while trying to match the argument list '(void)'	error C2440: 'specialization' : cannot convert from 'int (__thiscall Foo::* )(void) const' to 'int Foo::* const ' There is no context in which this conversion is possibleerror C2973: 'Bar<T>::add' : invalid template argument 'int (__thiscall Foo::* )(void) const' with [ T=Foo ] see declaration of 'Bar<T>::add' with [ T=Foo ]error C2668: 'Bar<T>::add' : ambiguous call to overloaded function with [ T=Foo ]    could be 'void Bar<T>::add<int,int Foo::getB(void) const>(void)' with [ T=Foo ]    or 'void Bar<T>::add<int,int Foo::getB(void) const>(void)' with [ T=Foo ]    while trying to match the argument list '(void)'


Works in GCC though :/
That's Microsoft. There are ore bugs like that in VC. That's why I only use it when I have to (it optimizes better than Borland).

class Foo {public:    operator int *();    int operator[](unsigned i);};int main(){    Foo foo;    int i = 5;    foo; // error}

This topic is closed to new replies.

Advertisement