Moin Zusammen,
ich habe in meinem Code mehrere Koordinatensysteme (abc, ab, dq)
zwischen denen ich munter hin und her transformiere. Dafür habe ich mir
3 Klassen geschrieben die die ganzen Operatoren überladen.
1
template<typenameT>
2
classSystemABC;
3
template<typenameT>
4
classSystemDQ;
5
template<typenameT>
6
classSystemAlphaBeta;
7
8
/// Mit Operatoren wie diesem:
9
///< assignment operator with clark transformation
Das funktioniert wunderbar, aber ich habe auch Arrays der Vektoren wie:
1
std::array<SystemAlphaBeta<float>,4>buffer
Wenn ich den Array des SystemAlphaBeta dem SystemABC zuweisen will muss
ich eine nervige Schleife alla basteln:
1
2
// convert current samples with clark to statonary frame;
3
for(std::size_ti=0;i<i_abc.size();i++)
4
{
5
i_alpha_beta[i]=i_abc[i];
6
}
Das nervt wäre aber noch zu verschmerzen. Bei komplizierterem, wie einer
Zuweisung eines Arrays auf eine einzelne Instanz der Klasse um z.b. den
Mittelwert auszuwerten, handle ich mir unnötig doppelten Code ein.
Dafür würde ich eigentlich gern den operator= der Template Instanz
std::array<SystemAlphaBeta<float>, N> überladen. Geht sowas? Sonst fällt
mir nur ein das Template der Klassen um einen Parameter mit der Array
länge zu erweitern.
Gruß
Tec
tictactoe schrieb:> Nein, das geht nicht. Man macht das ohne Schleife eher so:#include> <algorithm>>> std::copy(i_abc.begin(), i_abc.end(), i_alpha_beta.end());
Kleinen Fehler korrigiert:
Da stellt sich mir die Frage nutzt copy meinen Zuweisungsoperator,
sprich die korrekte Transformation oder kopiert er einfach Speicher.
Die C++ Reference beschreibt die Implementierung nur recht schwammig.
In practice, implementations of std::copy avoid multiple assignments and
use bulk copy functions such as std::memmove if the value type is
TriviallyCopyable
Für mich bedeutet das, mir fliegt diese stelle im Code compilerabhängig
um die Ohren. Je nachdem wie copy implementiert ist.
Hallo,
Dazu ein Gedanke als Anfänger:
überladen geht nicht, operator= ist Member.
Man kann aber doch eine Template Spezialisierung nur für den gewünschten
Operator angeben? Also nicht die ganze Klasse spezialisieren, sondern
nur den gewünschten operator= ?
vlg
Timm
Tec N. schrieb:> In practice, implementations of std::copy avoid multiple assignments and> use bulk copy functions such as std::memmove if the value type is> TriviallyCopyable>> Für mich bedeutet das, mir fliegt diese stelle im Code compilerabhängig> um die Ohren. Je nachdem wie copy implementiert ist.
Tut es nicht.
http://en.cppreference.com/w/cpp/concept/TriviallyCopyable
Oliver
Tec N. schrieb:> Da stellt sich mir die Frage nutzt copy meinen Zuweisungsoperator,> sprich die korrekte Transformation oder kopiert er einfach Speicher.>> Die C++ Reference beschreibt die Implementierung nur recht schwammig.>> In practice, implementations of std::copy avoid multiple assignments and> use bulk copy functions such as std::memmove if the value type is> TriviallyCopyable>> Für mich bedeutet das, mir fliegt diese stelle im Code compilerabhängig> um die Ohren. Je nachdem wie copy implementiert ist.
Da hättest du etwas weiter lesen sollen.
Der Hinweis steht under "Notes" auf
http://en.cppreference.com/w/cpp/algorithm/copy .
In dem Text ist TriviallyCopyable ein Link mit weiteren Erklärungen
(http://en.cppreference.com/w/cpp/concept/TriviallyCopyable).
Unter Requirements steht unter anderem
> every copy assignment operator is trivial or deleted
Hier ist trivial wieder ein Link auf weitere Erklärungen
(http://en.cppreference.com/w/cpp/language/copy_assignment#Trivial_copy_assignment_operator).
Dort ist der erste Punkt
> it is not user-provided (meaning, it is implicitly-defined or defaulted) , , and
if it is defaulted, its signature is the same as implicitly-defined (until C++14);
Also ist zumindest SystemAlphaBeta nicht TriviallyCopyable, da du einen
eigen operator= lieferst und es wird kein memmove benutzt. Wenn du
sicher gehen willst, dass deine Typen nicht TriviallyCopyable sind
kannst du das mit dem type_trait is_trivially_copyable
(http://en.cppreference.com/w/cpp/types/is_trivially_copyable) testen.
Timm R. schrieb:> Man kann aber doch eine Template Spezialisierung nur für den gewünschten> Operator angeben? Also nicht die ganze Klasse spezialisieren, sondern> nur den gewünschten operator= ?
Was man in namespace std machen darf ist ziemlich eingeschränkt
(http://en.cppreference.com/w/cpp/language/extending_std). Im
wesentlichen darf man nur in speziellen Fällen class templates
spezialisieren.
Unter anderem gilt
> It is undefined behavior to declare a full specialization of any member function
of a standard library class template
Man darf also operator= (member function) von std::array (standard
library class template) nicht überladen.
Davon abgesehen müsste operator= erstmal eine template Memberfunktion
sein, sonst ist man bei Overloading, was verboten ist.
Tec N. schrieb:> Ich will eigentlich nur sowas machen können:> std::array<SystemAlphaBeta<float>, 4> left_array => std::array<SystemABC<float>, 4> right_array;
Brauchst du das tatsächlich als vollen Zuweisungsoperator?
Wenn nicht, schreib dir halt eine Kopierfunktion. Da wird dann zwar
deine Schleife von weiter oben drinstecken, aber im Endeffekt wird jede
Implemetierung darauf hinauslaufen.
Oliver
Hallo mh,
ups, wenn der Standard das für std:: verbietet, sollte man wohl die
Finger davon lassen.
Trotzdem eine Frage:
mh schrieb:> Davon abgesehen müsste operator= erstmal eine template Memberfunktion> sein, sonst ist man bei Overloading, was verboten ist.
Der folgende operator = ist keine template Memberfunktion. Bedeutet das,
dass Du sagst, dass das, was ich da mache, overloading und nicht
specialization ist?
1
// Ich habe ... do something und sowas weggelassen, damit der Code compilierbar ist
mh schrieb:> Da hättest du etwas weiter lesen sollen.>> Der Hinweis steht under "Notes" auf> http://en.cppreference.com/w/cpp/algorithm/copy .> In dem Text ist TriviallyCopyable ein Link mit weiteren Erklärungen> (http://en.cppreference.com/w/cpp/concept/TriviallyCopyable).
Stimmt hab ich nicht gelesen :) tl,dr.
Demnach sind alle beteiligten Klassen nicht TriviallyCopyable, dann ist
std::copy ein sehr schöner Ansatz.
Timm R. schrieb:> Der folgende operator = ist keine template Memberfunktion. Bedeutet das,> dass Du sagst, dass das, was ich da mache, overloading und nicht> specialization ist?> // Ich habe ... do something und sowas weggelassen, damit der Code> compilierbar ist> template <typename T>> class test {> public:> T& operator=(const T& in) {> return daten;> }> private:> T daten;> };>> template<>> std::string& test<std::string>::operator=(const std::string& in) {> return daten;> }
Das wäre ja genau das was ich erreichen wollte. Dass man ein Template
ohne Parameter spezialisieren kann, wusste ich gar nicht. Mal sehen was
der GCC dazu sagt.
Wenn das keine bad practice ist werde ich das mal so versuchen.
Es geht ja auch darum das der zu implementierende Code so simpel wie
möglich wird. Da ist = einfach charmant, wenn sich der Code/Compiler um
den Rest kümmert.
../modules/unit/system_abc.hpp:126:53: error: template-id 'operator=<>' for 'const std::array<unit::SystemABC<float>, 4>& std::array<unit::SystemABC<float>, 4>::operator=(const std::array<unit::SystemAlphaBeta<float>, 4>&)' does not match any template declaration
Nur kann ich die Beschwerde nicht verstehen das template hat 2
Parameter! N Komma oder so habe ich auch nicht vergessen (glaub ich).
Hat noch jemand Ideen, sonst bleibe ich wohl bei der std::copy Variante,
das läuft.
Danke dafür schon mal.
std::array hat einen vom compiler generierten operator=.
Timm R. schrieb:> Der folgende operator = ist keine template Memberfunktion. Bedeutet das,> dass Du sagst, dass das, was ich da mache, overloading und nicht> specialization ist?>
Ich würd sagen, dass das eine Spezialisierung der Klasse test<T> für T =
std::string ist. operator= ist in diesem Fall kein Memberfunktions
Template.
Wenn operator= ein Template wäre und du möchtest es spezialisieren,
sieht das ungefähr so aus (keine Garantie für Korrektheit)
Wenn du die Methode spezialisierst, musst du auch die Klasse
spezialisieren.
Und bitte schreibe niemals einen operator=, der etwas anderes als *this
zurück liefert.
Voraussetzung ist, dass die vom Standard vorgegebenen Member-Funktionen
wie vom Standard definiert verhalten.
Ich würde aber die Finger davon lassen und bei std::copy bleiben.
>// dann brauchst du aber auch Default-Assignment:
14
>array&operator=(constarray&right){
15
>// ...
16
>return*this;
17
>}
18
>};
19
>}
20
>
> Voraussetzung ist, dass die vom Standard vorgegebenen Member-Funktionen> wie vom Standard definiert verhalten.>> Ich würde aber die Finger davon lassen und bei std::copy bleiben.
Das ist mir wirklich zu heiß, das versteht kein anderer mehr und ich in
5 Jahren wahrscheinlich auch nicht.
mh schrieb:> Wenn operator= ein Template wäre und du möchtest es spezialisieren,> sieht das ungefähr so aus (keine Garantie für Korrektheit)template> <typename T>> class test {> public:> template <typename U>> T& operator=(const U& in) {> return daten;> }> private:> T daten;> };>> template <>> template <>> std::string& test<std::string>::operator=<std::string>(const> std::string& in) {> return daten;> }
Hallo,
mh schrieb:> Und bitte schreibe niemals einen operator=, der etwas anderes als *this> zurück liefert.
versprochen!
> Ich würd sagen, dass das eine Spezialisierung der Klasse test<T> für T => std::string ist. operator= ist in diesem Fall kein Memberfunktions> Template.
Wenn das eine Spezialisierung der Klasse wäre, wäre dann Folgendes nicht
fehlerhaft wegen Redefinition?
Hallo,
Tec N. schrieb:> eribt: invalid use of incomplete type 'struct> std::array<unit::SystemAlphaBeta<T>, N>'> [/c]> Muss ich wirklich alles voll spezifizieren also Arraylänge N und den> Basistypen T auch?
du solltest es eh nicht machen, wenn der Standard sagt, dass es böse ist
und du weißt ja schon, dass die Standardoperation passt.
Aber: Ich glaube nicht, dass es geht. Das was ich vorgeschlagen habe,
egal ob es sich nun um class specialization handelt oder um function
specialization, geht nur mit members die auch deklariert sind. Implizite
members kann man so nicht spezialisieren und = ist bei array implizit,
wie mh bestätigt.
vlg
Timm
Timm R. schrieb:>> eribt: invalid use of incomplete type 'struct>> std::array<unit::SystemAlphaBeta<T>, N>'>> [/c]>> Muss ich wirklich alles voll spezifizieren also Arraylänge N und den>> Basistypen T auch?>> du solltest es eh nicht machen, wenn der Standard sagt, dass es böse ist> und du weißt ja schon, dass die Standardoperation passt.>> Aber: Ich glaube nicht, dass es geht. Das was ich vorgeschlagen habe,> egal ob es sich nun um class specialization handelt oder um function> specialization, geht nur mit members die auch deklariert sind. Implizite> members kann man so nicht spezialisieren und = ist bei array implizit,> wie mh bestätigt.
Sehe ich auch so. Danke für die Hilfe.