Fórumok
Üdv!
Miért van az, hogy az alábbi kódban a T template paramétert nem bírja kitalálni a compiler (g++):
#include<iostream>
#include<iomanip>
#include<boost/numeric/ublas/vector.hpp>
#include<boost/numeric/ublas/io.hpp>
template<typename T, size_t n> boost::numeric::ublas::vector<T> vecFromArray(const std::array<T, n> x){
boost::numeric::ublas::vector<T> retVal(n);
std::copy(x.begin(), x.end(), retVal.begin());
return retVal;
}
int main(){
boost::numeric::ublas::vector a = vecFromArray({0.0, 1.0, 2.0});
std::cout << a << std::endl;
return 0;
}
és szájba kell rágni neki úgy, hogy
boost::numeric::ublas::vector a = vecFromArray<double, 3>({0.0, 1.0, 2.0});
ami persze nem jó, mert neked kell odafigyelned, hogy a szám és a lista hossza stimmeljen. (Nyilván meg lehet oldani, ha az ember ír egy ilyen függvényt külön, ami eleve egy std::initializer_list-et kap, de most nem ez a kérdés. Meg akkor, ha mind a kettő kell, akkor duplikálva van egy kis kód.)
Szerk.: kódismétlés nélkül megoldható, de azért érdekelne a válasz az előzőre:
#include<iostream>
#include<iomanip>
#include<initializer_list>
#include<boost/numeric/ublas/vector.hpp>
#include<boost/numeric/ublas/io.hpp>
template<class T1, class T2> T2 vectorConvert(const T1 &x){
T2 convertedVector(x.size());
std::copy(x.begin(), x.end(), convertedVector.begin());
return convertedVector;
}
int main(){
auto a = vectorConvert<std::initializer_list<double>, boost::numeric::ublas::vector<double> >({0.0, 1.0, 2.0});
std::cout << a << std::endl;
return 0;
}
Hozzászólások
Szerinted melyik aritmetikával kellene dolgoznia, ha nem definiálod a <double>-t?
- float?
- double?
Ezt kellett neked eldöntened és explicit odaírnod.
C/C++-ban nem úgy van, hogy az, hogy 2.0 egy double, és ha egy literalt floatként akarok, az 2.0f, ha meg long doubleként, az 2.0l?
Mellesleg az sem megy (ugyanaz a hibaüzenet), hogy
Tartok attól, hogy bár elvileg "kimatekozható" a generic láncolatának végén a típus, de a ilyen mélységű generic továbbvitelnél (vagy bármi miatt) nem óhajtja mégsem kimatekozni a C++ fordító.
Mutatok Rust-ban egy hasonlóan furi példát: mindhárom sort külön-külön nézd meg, főleg a középsőnél a hibaüzenetet. Itt is egy tervezési limitációval állunk szemben.
https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gi…
Az más kérdés, hogy jó-e ez a tervezési limitáció, vagy később fel lesz oldva. Jelenleg viszont ez adottság, ennek figyelembevételével kell írni a kódot.
ez szépen megy.
nem hiszem, hogy az eredeti megoldásban lehetne automatikus konverzió array és initializer_list között.
Igen, ezt nem írtam le világosan. Amikor azt írtam, hogy "ha az ember ír egy ilyen függvényt külön, ami eleve egy std::initializer_list-et kap", az alatt pont ezt értettem, hogy megírom initializer_list-re, array-ra, std::vector-ra, csak az ellentmondana annak a kódolási konvenciónak, hogy ne ismétlődjön kód. Az utólag beleszerkesztett verzió ezt már megoldja, de azért szeretném érteni, hogy a compiler miért nem tudta kikövetkezni a template argumentumokat.
nem ennyira értem, hogy mit nem értesz: ha talál egy függvényt, aminek bementő paramétere X<T> típusú, míg neked Y<T>-d van, és nincs automatikusa konverzió X és Y között (még ha a T template típus azonos is), akkor nem tud mit tenni.
Nem azt mondja. Ha azt mondaná, hogy nem talált olyan függvényt, ami brace-enclosed intializer list-et vár, akkor érteném, hogy nem hajlandó automatikus konverziót csinálni abból array-be. De azt mondja, hogy a T template argumentumot nem tudta kikövetkeztetni.
gondolom a T-re abból jönne rá, hogy van explicit konverzió X<T> és Y<T> között
Valami ilyenre gondoltam. Mondjuk az már magyaráz valamit, hogy az sem megy, hogy
csak úgy, hogy
ami persze array-ra szar, mert akkor be kell írnom külön a méretét is. Azt hiszem, elvileg a c++23 szerint meg lehetne csinálni két lépcsőben,
de a régebbi szabvány (és az én compilerem által részben támogatott, draft c++23) szerint az initializer_list nem lehet constexpr-ben.
array-ra c++17-ben is szuperul megy! nagyon tutti, imádom, a régi C-s xar inicializációs szenvedés helyett ezt használom, ahol csak lehet
Kösz, ez megy, legalábbis std::array-jal. Boost vectorral nem, de annyi baj legyen.
Ha a konténerre is templatizálni akarod, azt is lehet, pl
mondjuk nem értem, hogy ez miért megy vector-ral és miért nem megy initializer_list-tel.
Az ujabb c++ asszem eleg szigoru a konstansok tipusmeghatarozasanal (bocs, ritkan kell konkret szamokat beirnom, de volt mar vele gond)
De itt egy minta az tomb-meret-meghatarozashoz:
Szigoruan nem az enyem, de tobb helyen lattam mar. Ez alapjan be lehet allitani az osztaly hianyzo template parameteret.
Ez std:array-jal is megy? Mert int a[7]-tel deklarált array-jal, gondolom, igen.