2016-01-26 2 views
1

j'ai un vecteur ayant une valeur:C++ Définir une propriété rvalue dans une classe

obj={1.0,2.0,3.0, 4.0,5.0,6.0 ,7.0,8.0,9.0,10.0} 

En supposant que, mathématiquement obj est divisé en trois sous-vecteurs:

obj={P, Q , R} 

P={1.0,2.0,3.0}, Q={4.0,5.0,6.0} et R={7.0,8.0,9.0,10.0}

et j'ai besoin de changer les valeurs du sous-vecteur Q ie de l'inde x 3 à 6;

obj={1.0,2.0,3.0, -4.0,-5.0,-6.0 ,7.0,8.0,9.0,10.0} 

Non seulement infirment, mais aussi je veux être en mesure de faire toute autre action indépendamment sur un sous-vecteur de obj.

Le code suivant fonctionne:

#include <armadillo> 
#include <iostream> 

using namespace std; 

typedef arma::vec::fixed<10> x_vec; 

class B 
{ 
public: 
    x_vec data; 

    B(x_vec init) : 
     data(init) 
    { 
    } 

    inline decltype(data.subvec(0,2)) P() 
    { 
     return data.subvec(0,2); 
    } 

    inline decltype(data.subvec(3,5)) Q() 
    { 
     return data.subvec(3,5); 
    } 

    inline decltype(data.subvec(6,9)) R() 
    { 
     return data.subvec(6,9); 
    } 

}; 

int main() 
{ 
    B obj({1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0}); 
    cout<<"sizeof obj.data: "<<sizeof(obj.data)<<endl; 
    cout<<"sizeof obj: "<<sizeof(obj)<<endl; 
    cout<<"value of obj:"<<endl; 
    obj.data.print(); 

    obj.Q()=-obj.Q(); 

    cout<<"value of obj:"<<endl; 
    obj.data.print(); 

    return 0; 
} 

Résultat

sizeof obj.data: 192 
sizeof obj: 192 
value of obj: 
    1.0000 
    2.0000 
    3.0000 
    4.0000 
    5.0000 
    6.0000 
    7.0000 
    8.0000 
    9.0000 
    10.0000 
value of obj: 
    1.0000 
    2.0000 
    3.0000 
    -4.0000 
    -5.0000 
    -6.0000 
    7.0000 
    8.0000 
    9.0000 
    10.0000 

Cependant, comment le faire fonctionner sans parenthèse sur la propriété?

Je veux dire à l'aide

obj.Q=-obj.Q; 

au lieu de

obj.Q()=-obj.Q(); 

Je ne veux pas augmenter la taille de mon obj aussi.

Aussi, je suis à la recherche d'une solution polyvalente. Pas une solution qui annule juste un sous-vecteur de mon vecteur.


Mise à jour

Le code final fonctionne:

#include <armadillo> 
#include <iostream> 

using namespace std; 

typedef arma::vec::fixed<10> x_vec; 

struct wrapperB 
{ 
    wrapperB* operator ->() { return this; } 

    typedef decltype(std::declval<x_vec>().subvec(0, 2)) P_type; 
    typedef decltype(std::declval<x_vec>().subvec(3, 5)) Q_type; 
    typedef decltype(std::declval<x_vec>().subvec(6, 9)) R_type; 

    P_type& P; 
    Q_type& Q; 
    R_type& R; 

    wrapperB(P_type _p,Q_type _q,R_type _r) : 
     P(_p), Q(_q), R(_r) 
    { 
    } 
}; 

class B 
{ 
public: 
    x_vec data; 

    B(x_vec init) : data(init) {} 

    wrapperB operator ->() 
    { 
     return wrapperB(data.subvec(0,2), data.subvec(3,5), data.subvec(6,9)); 
    } 
}; 

int main() 
{ 
    B obj({1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0}); 
    cout<<"sizeof obj.data: "<<sizeof(obj.data)<<endl; 
    cout<<"sizeof obj: "<<sizeof(obj)<<endl; 
    cout<<"value of obj:"<<endl; 
    obj.data.print(); 

    obj->Q=-obj->Q; 

    cout<<"value of obj:"<<endl; 
    obj.data.print(); 

    return 0; 
} 
+0

Mettre en œuvre le unaire opérateur moins: http://stackoverflow.com/questions/2155275/how-to- surcharge-unaire-moins-opérateur-en-c – Pierre

+0

@Pierre Je cherche une solution générale. Que diriez-vous de 'obj.myvec = {0.7, -0.1,0.8}'? – ar2015

+0

Opérateur d'assignation @Pierre sur la classe 'myvec' ou' B'? – ar2015

Répondre

1

avec l'utilisateur défini operator ->, vous pouvez abuser de celui-ci d'avoir

obj->myvec=-obj->myvec; 

Par exemple:

template <typename T> 
struct wrapper 
{ 
    wrapper<T>* operator ->() { return this; } 

    std::vector<T>& myvec; 
}; 

template <typename T> 
class B 
{ 
public: 
    std::vector<T> data; 

    B(const std::vector<T>& init) : data(init) {} 

    wrapper<T> operator ->() { return {data}; } 

}; 

Demo

Donc, dans votre cas, le code pourrait être quelque chose comme:

struct wrapperB 
{ 
    wrapperB* operator ->() { return this; } 

    decltype(std::declval<x_vec>().subvec(0, 2))& P; 
    decltype(std::declval<x_vec>().subvec(3, 5))& Q; 
    decltype(std::declval<x_vec>().subvec(6, 9))& R; 
}; 

class B 
{ 
public: 
    x_vec data; 

    B(x_vec init) : data(init) {} 

    wrapperB operator ->() 
    { 
     return {data.subvec(0,2), data.subvec(3,5), data.subvec(6,9)}; 
    } 
}; 
+0

@ ar2015: Je n'ai pas 'arma :: vec :: fixed <10>', mais vous pouvez organiser mon exemple pour qu'il fonctionne avec 'data.subvec (3,5)'. – Jarod42

+0

@ ar2015: code ajouté. 'wrapperB' est la structure avec l'interface que vous voulez. 'B :: operator ->' devrait retourner l'encapsuleur avec les données correctes. Veillez à ce que si 'subvec' renvoie par valeur (un proxy par exemple), vous devez supprimer la référence pour' P', 'Q',' R'. – Jarod42

+0

@ ar2015: constructeur manquant pour 'wrapperB' qui prend les 3 références que je comprends. – Jarod42