2016-03-13 3 views
2

Рассмотрите класс card, который имеет два открытых элемента: int suit и int value, а также функцию шаблона, которая сортирует массив карт членом, который я передаю через указатель на элемент, например:Указатель на частный элемент данных класса

//class card with public members 
class card{ 
public: 
    int suit; 
    int value; 
}; 

//sorting algorithm 
template<typename m_pointer, typename iterator, typename Functype> 
void sort_array(m_pointer member, iterator begin, iterator end, Functype pred){ 
    iterator iter1=begin; 
    while(iter1!=end && ++iter1!=end){ 
    iterator iter2=iter1; 
    while(iter2!=begin){ 
     iterator iter3=iter2; 
     --iter3; 
     //here i use the pointer-to-member to sort the cards 
     if(pred((*iter3).*member, (*iter2).*member)){ 
      std::swap(*iter3, *iter2); 
     } 
     else break; 
     --iter2; 
    } 
    } 
} 

int main(){ 
    card array[3]={{3,1},{2,3},{4,5}}; 
    //let's sort the cards by the suit value in a decreasing order 
    sort(&card::suit, array, array+3, [](int a, int b){return a<b;}); 
} 

Если член карты suit является публичной нет, очевидно, не проблема, но что на самом деле я не ожидал, что тот же код не дает каких-либо проблем, даже если я объявляю suit или value как частные члены.

class card{ 
    int suit; 
    int value; 
    public://adding this for clarity, read forward 
    int* pointer_to_suit();  
}; 

Из того, что я знаю, я не должен быть в состоянии получить доступ к частным членам вне класса, и единственным способом передать указатель на член к частному члену через функцию-член, которая возвращает адрес члена, как это, например:

//function member of the class card 
int* card::pointer_to_suit(){ 
    return &suit; 
} 

Итак, почему это возможно, что приведенный выше код (один с шаблоном) работает?

EDIT: Ok, приведенный выше код не компилируется по себе, но по какой-то причине следующий код компилироваться мне. Я выложу весь код, так как я понятия не имею, где трюк для того, чтобы работать может быть, извините за беспорядок:

template<typename m_pointer, typename iterator, typename Functype> 
void sort_array(m_pointer member, iterator begin, iterator end, Functype pred){ 
iterator iter1=begin; 
while(iter1!=end && ++iter1!=end){ 
    iterator iter2=iter1; 
    while(iter2!=begin){ 
     iterator iter3=iter2; 
     --iter3; 
     if(pred((*iter3).*puntatore, (*iter2).*puntatore)){ 
      std::swap(*iter3, *iter2); 
     } 
     else break; 
     --iter2; 
    } 
    } 
} 


class card{ 
    int suit; 
    int value; 
public: 
card(): suit(0), value(0) {} 
card(int a, int b): suit(a), value(b){} 
bool operator==(card a){return (suit==a.get_s() && value==a.get_v());} 
bool operator!= (card a){return !(*this==a);} 

void set_values(int a, int b){suit=a; value=b;} 
int get_v(){return value;} 
void set_v(int v){value=v;} 
int get_s(){return suit;} 
void set_s(int s){suit=s;} 
double points_card(); 
}; 


template<typename iterator> 
void ordina(iterator begin, iterator end, short (&suit)[4]){ 

for(int i=0; i<4; i++) suit[i]=0; 

iterator it1=begin; 
while(it1!=end){ 
    if((*it1).get_s()==1) suit[0]+=1; 
    else if((*it1).get_s()==2) suit[1]+=1; 
    else if((*it1).get_s()==3) suit[2]+=1; 
    else if((*it1).get_s()==4) suit[3]+=1; 
    ++it1; 
} 

sort_array(&carte::suit, begin, end, [](char a, char b){ 
    if(b==0) return false; 
    else if(a==0) return true; 
    return (a>b); 
}); 

sort_array(&carte::value, begin, begin+suit[0], [](int a, int b){return (a<b);}); 
sort_array(&carte::value, begin+suit[0], begin+suit[0]+suit[1], [](int a, int b){return (a<b);}); 
sort_array(&carte::value, begin+suit[0]+suit[1], begin+suit[0]+suit[1]+suit[2], [](int a, int b){return (a<b);}); 
sort_array(&carte::value, begin+suit[0]+suit[1]+suit[2], begin+suit[0]+suit[1]+suit[2]+suit[3],[](int a, int b){return (a<b);}); 
} 

int main(){ 
card array[5]={{2,3},{1,2},{3,4},{4,5},{3,2}}; 
short suits[4]={1,1,2,1}; 
ordina(array, array+5, suits); 
return 0; 
} 

EDIT 2: Да, он работает http://coliru.stacked-crooked.com/a/d1795f0845770fcb. Обратите внимание, что код здесь не переведен, и есть несколько строк, которые я не добавлял для краткости.

EDIT 3: Как уже упоминалось в Барри ответить https://stackoverflow.com/a/35978073/5922196, это gcc ошибка компилятора. Я использовал g++ 4.9.2, и эта ошибка по-прежнему не решена.

+1

Не могли бы вы включить класс карты? –

+1

Почему вы заново изобретаете std :: sort()? –

+0

Какой компилятор/версия вы используете, потому что он не компилировался в Visual Studio или GCC для меня, даже после того, как я исправил орфографию «class». http://ideone.com/vnwEkc – kfsone

ответ

3

Поздравляем, вы обнаружили ошибку в gcc! Ниже приведен пример минимально. Обратите внимание, что когда мы говорим минимальный, мы действительно имеем в виду минимальный. Я нашел это, просто повторно удалив большую часть ваших строк кода. Кроме того, всегда включайте то, что вы использовали. Помогло бы.

GCC компилирует это:

class X { 
    int mem; 
}; 

template <class T> 
auto foo(T) { 
    return &X::mem; 
} 

int main() { 
    auto p = foo(0); 
} 

лязг не делает. clang прав. Это ошибка gcc 41437.