Bonjour à tous.

Je suis en train d'implémenter une bibliothèque d'algèbre linéaire pour des petits vecteurs et matrices + des fonctions répondant à mon domaine de recherche et j'ai un petit problème. Je connaissais vaguement le CRTP, et après quelques tests, il s'avère que c'est bien adapté à ce que je veux faire. J'ai donc fait un petit programme de test, mais il reste un souci.

Voici d'abord le programme de test (le pb est à l'avant dernière ligne) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include <iostream>
#include <initializer_list>
#include <type_traits>
 
// Abstract class
template<class TCRTP, class T, unsigned int TSIZE> class AbstractArray
{
    // Constructor
    public:
        inline AbstractArray() : _data{}
        {
            std::cout<<"AbstractArray::AbstractArray()"<<std::endl;
        }
 
    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline AbstractArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)
        {
            std::cout<<"AbstractArray::AbstractArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
            for(unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = rhs[i];
            }
        }
 
    // Initializer list constructor
    public:
        template<class T0> inline AbstractArray(const std::initializer_list<T0>& rhs)
        {
            std::cout<<"AbstractArray::AbstractArray(const std::initializer_list<T0>& rhs)"<<std::endl;
            const T0* it = rhs.begin();
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = *it;
                ++it;
            }
        }
 
    // Destructor
    public:
        inline ~AbstractArray()
        {
            std::cout<<"AbstractArray::~AbstractArray()"<<std::endl;
        }
 
    // Subscript operator
    public:
        inline const T& operator[](const unsigned int i) const
        {
            std::cout<<"AbstractArray::operator[](const unsigned int i) const"<<std::endl;
            return _data[i];
        }
        inline T& operator[](const unsigned int i)
        {
            std::cout<<"AbstractArray::operator[](const unsigned int i)"<<std::endl;
            return _data[i];
        }
 
    // Assignment operator
    public:
        template<class TCRTP0, class T0> inline AbstractArray<TCRTP, T, TSIZE>& operator=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)
        {
            std::cout<<"AbstractArray::operator=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)"<<std::endl;
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = rhs[i];
            }
            return *this;
        }
 
    // Sum assignment
    public:
        template<class TCRTP0, class T0> inline AbstractArray<TCRTP, T, TSIZE>& operator+=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)
        {
            std::cout<<"AbstractArray::operator+=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)"<<std::endl;
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] += rhs[i];
            }
            return *this;
        }
 
    // Sum operator
    public:
        template<class T0> inline AbstractArray<TCRTP, typename std::common_type<T, T0>::type, TSIZE> operator+(const AbstractArray<TCRTP, T0, TSIZE>& rhs) const
        {
            return AbstractArray<TCRTP, typename std::common_type<T, T0>::type, TSIZE>(*this) += rhs;
        }
 
    // Data members
    protected:
        T _data[TSIZE];
};
 
// Array class
template<class T, unsigned int TSIZE> class NArray : public  AbstractArray<NArray<T, TSIZE>, T, TSIZE>
{
    // Constructor
    public:
        inline NArray() : AbstractArray<NArray<T, TSIZE>, T, TSIZE>()
        {
            std::cout<<"NArray::NArray()"<<std::endl;
        }
 
    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline NArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs) : AbstractArray<NArray<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NArray::NArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
        }
 
    // Initializer list constructor
    public:
        template<class T0> inline NArray(const std::initializer_list<T0>& rhs) : AbstractArray<NArray<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NArray::NArray(const std::initializer_list<T0>& rhs)"<<std::endl;
        }
 
    // Destructor
    public:
        inline ~NArray()
        {
            std::cout<<"NArray::~NArray()"<<std::endl;
        }
};
 
// Vector class
template<class T, unsigned int TSIZE> class NVector : public  AbstractArray<NVector<T, TSIZE>, T, TSIZE>
{
    // Constructor
    public:
        inline NVector() : AbstractArray<NVector<T, TSIZE>, T, TSIZE>()
        {
            std::cout<<"NVector::NVector()"<<std::endl;
        }
 
    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline NVector(const AbstractArray<TCRTP0, T0, TSIZE> &rhs) : AbstractArray<NVector<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NVector::NVector(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
        }
 
    // Initializer list constructor
    public:
        template<class T0> inline NVector(const std::initializer_list<T0>& rhs) : AbstractArray<NVector<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NVector::NVector(const std::initializer_list<T0>& rhs)"<<std::endl;
        }
 
    // Destructor
    public:
        inline ~NVector()
        {
            std::cout<<"NVector::~NVector()"<<std::endl;
        }
};
 
// Main
int main()
{
    NArray<double, 3> a1({1., 2., 3.});
    std::cout<<std::endl;
    NArray<int, 3> a2({4., 5., 6.});
    std::cout<<std::endl;
    NArray<double, 3> a3({7., 8., 9.});
    std::cout<<std::endl;
    NVector<double, 3> v1({11., 12., 13.});
    std::cout<<std::endl;
    NVector<double, 3> v2({14., 15., 16.});
    std::cout<<std::endl;
    NVector<double, 3> v3({17., 18., 19.});
    std::cout<<std::endl;
    NVector<int, 3> v4({20., 21., 22.});
    std::cout<<std::endl;
    a1 = a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> a1 = "<<a1[0]<<" "<<a1[1]<<" "<<a1[2]<<std::endl;
    std::cout<<std::endl;
    v1 = a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    v1 += a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    v1 = a3+a3;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    //v2 = v3+v4; // <- This line does not work : "error : no match for "operator+" in "v3+v4"
    std::cout<<std::endl;
    return 0;
}
Bref tout fonctionne à part quand j'appelle v2 = v3+v4 où v2 est un vecteur de double, v3 est un vecteur de double et v4 est un vecteur d'integer. (la somme de la ligne précédente v1 = a3 + a3, elle fonctionne, où tout est du même type).

Auriez vous une idée pour corriger le problème ?

D'autre part, si vous avez des idées pour améliorer l'efficacité ou la qualité du code (ou si vous constatez des trucs "dangereux" dans le code qui précède), avant que je me lance dans la conversion de l'implémentation actuelle à une implémentation basée sur cet exemple, vos conseils seront grandement appréciés (par contre, je ne vais pas me lancer dans de la "vraie" métaprogrammation car le loop unrolling du compilo connaissant la taille fixe des tableaux me suffit bien).

Merci infiniment