2016-04-07 11 views
2

Ich definiere eine Gürteltier-Matrix und ich versuche, es über Initialisiererlisten gemäß seiner manual zu initialisieren.C++: Armadillo Spalte Matrix Initialisierung mehrdeutig

Es ist in Ordnung, wenn ich nicht versuche, eine Spaltenmatrix zu definieren.

Warum ist es ambivalent?

#include <armadillo> 

int main() 
{ 
    // ok : square matrix 
    arma::mat A={{1.0,2.0},{3.0,4.5}}; 

    // ok: row matrix 
    arma::mat B={3.5,4.0}; 

    // error: conversion from ‘<brace-enclosed initializer list>’ to 
    // ‘arma::mat {aka arma::Mat<double>}’ is ambiguous 
    arma::mat C={{3.5},{4.0}}; 

    // ok: column matrix 
    arma::mat D=arma::mat({3.5,4.0}).t(); 

    return 0; 
} 

Antwort

5

Es ist ein Problem mit dem C++ 11/14-Standard.Da es in jedem inneren Satz nur ein Element gibt, besagt der Standard im Wesentlichen, dass {{3.5},{4.0}} auch als {3.5,4.0} interpretiert werden kann. Mit anderen Worten, {3.5} kann implizit in double(3.5) konvertiert werden. Dies führt zu der Mehrdeutigkeit zwischen den beiden Konstruktoren.

Eine mögliche Lösung ist die Armadillo Spaltenvektor Konstruktor zu verwenden:

arma::mat C = arma::colvec({3.5, 4.0}); 
2

Ich denke, es hat etwas mit Definitionen von Array in C++ statt Armadillo zu tun.
Es scheint, dass Sie Matrizen von Arrays initialisieren. Daher muss Ihr richtiger Wert nach dem C++ - Standard ein eindeutiges Array sein. Lassen Sie uns die richtigen Werte Ihrer dritten Definition sehen:
{{3.5},{4.0}}
Es bedeutet nicht eine 1 * 2 Spaltenmatrix mit der ersten Zeile als 3,5 und der zweiten Zeile als 4,0. Es stellt eine Matrix mit zwei Zeilen dar, die mit 3,5 bzw. 4,0 begonnen wurden. Möglicherweise haben Sie gelegentlich eine solche Definition gesehen: double d_array[2][6] = {{3.5},{4.0}};
Nur die nullten Elemente jeder Zeile in d_array werden initialisiert. Da dieser rechte Wert jedem 2D-Array mit zwei oder mehr Zeilen zugewiesen werden kann, ist er nicht eindeutig und kann einem Matrixinitialisierer nicht zugewiesen werden.
Ich bin nicht sicher, ob es Sinn macht, und wenn es etwas falsches gibt, bitte beachten Sie mich, indem Sie diese Antwort unten kommentieren.

+0

ich Ihnen widersprechen, wie dieser Code vollständig mit quadratischen Matrizen arbeitet. Wenn ich Zahlen ohne extra Umbruch anlege, wird das eine Zeilenmatrix definieren. Der gürteltierbezogene Code für 'operator =' kann [hier] (https://github.com/RcppCore/RcppArmadillo/blob/6450efdb9b727539dabd13467db5a7a0f25c8b38/inst/include/armadillo_bits/Mat_bones.hpp#L762) oder in der Nähe gefunden werden. – ar2015

+0

@mtall, existiert irgendeine andere Lösung oder 'arma :: mat ({3.5.4.0}). T(); ist der einzige Weg? – ar2015

+0

@Mtall, es hat funktioniert. Vielen Dank. Könnten Sie es bitte als Antwort lassen, damit ich die Frage schließen kann? – ar2015

2

Einfache Antwort: die Regel der Standardspezifikation.

Zuerst Ihre Aussage

arma::mat C={{3.5},{4.0}}; 

Kopie initialisieren ein Objekt C. (Copy-Initialisierung stellt nicht unbedingt eine Kopie-Konstruktor) Der Initialisierer ist Initialisierer-Liste und Liste Initialisierung wird eingesetzt. Da Objekt C ist Klasse, InitialisierungslisteKonstruktor wird zuerst gesucht.

armadillo::Mat<eT> hat zwei Initialisierer-ListeKonstruktor:

// defined in "<include-dir>/armadillo_bits/Mat_bones.hpp" 
Mat(const std::initializer_list<eT>& list); 
Mat(const std::initializer_list< std::initializer_list<eT> >& list); 

Diese Kandidat Funktion s in der Überladungsauflösung sind. Um die beste funktionsfähige Funktion zu bestimmen, wird die partielle Reihenfolge der impliziten Umwandlung von Initialisierungsliste zu jedem Parameter betrachtet. In diesem Fall wird ListeninitialisierungSequenz verwendet. {3.5} und {4.0} können beide in eT und std::initializer_list<eT> konvertiert werden. Wichtiger Hinweis hier ist, dass es für beide Fälle implizite Konvertierungen gibt. Die Spezifikation definiert, dass diese Art der Umwandlung die schlechteste Reihenfolge hat, und diese beiden Konstruktoren sind am schlechtesten, mit anderen Worten, dieselbe Reihenfolge, was zu einer mehrdeutigen Überladungsauflösung führt.

Verwandte Themen