2015-07-10 19 views
5

Il seguente codice:Come utilizzare un cast esplicito per sopprimere questo avviso?

#include <cstdint> 
#include <vector> 
#include <boost/range/irange.hpp> 

int main() { 
    int64_t first = 0, last = 10; 
    std::vector<double> result = boost::copy_range<std::vector<double>>(boost::irange(first, last)); 
} 

genera l'avviso (e oltre 100 linee di analisi dello stack delle chiamate basato su modelli):

1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xmemory0(600): 
warning C4244: 'initializing' : conversion from 'unsigned __int64' to 'double', possible loss of data 

voglio dire al compilatore che non mi interessa che la mia int64_t sono convertiti in double. Invece non voglio usare un int a 32 bit. Di solito userei static_cast<double>(my64BitInt) per risolvere questo problema, ma non funzionerà per un intervallo. In questo momento sto ricorrendo alla direttiva del compilatore per sopprimere l'avvertimento, ma non è l'ideale.

Modifica: ecco uno pastebin con l'output del compilatore completo.

+0

1) È possibile eliminare gli avvisi nelle impostazioni di progetto piuttosto che con pragma, se si pensa che non avrete mai preoccupate per questo. 2) Perché 'first' e' last' sono dichiarati come 'int64_t' invece di' double'? – celticminstrel

+0

La direttiva @celticminstrel in Visual Studio consente di sopprimere gli avvisi su determinate righe di codice e di lasciarli sul posto per il resto del progetto. – IronMensan

+0

Sono consapevole. (Puoi farlo anche con clang/gcc, anche se la sintassi è un po 'diversa.) Lo stavo solo sottolineando in parte perché personalmente trovo che quel particolare avvertimento sia inutile più spesso che utile e in parte nel caso in cui tu sia d'accordo. – celticminstrel

risposta

2

Penso che sarà necessario utilizzare std::transform anziché boost_range. Inoltre, preferisco di gran lunga usare lo boost numeric cast sullo static_cast integrato.

Ecco un esempio di lavoro:

template <class DST, class SRC> 
struct Convert 
{ 
    DST operator()(SRC s) { return boost::numeric_cast<DST>(s); } 
}; 

int main(int argc, const char* argv[]) 
{ 
    int64_t first = 0, last = 10; 
    auto my_range = boost::irange(first, last); 
    std::vector<double> result(my_range.size()); 
    std::transform(my_range.begin(), my_range.end(), result.begin(), Convert<double, int64_t>()); 

    std::cout << "result: "; 
    std::copy(result.begin(), result.end(), std::ostream_iterator<double>(std::cout, ", ")); 

} 

Il codice precedente utilizza transform con funtore Convert. Se si preferisce un lambda, questo funziona (ed è più succinta) troppo:

std::transform(my_range.begin(), my_range.end(), result.begin(), 
       [](int64_t ival) { 
        return boost::numeric_cast<double>(ival); 
       } 
       ); 

EDIT Aggiungi variante iota troppo

Come sehe sottolinea, per generare un vettore di doppi nel range [0 , 10), è possibile utilizzare la funzione std library iota (da #include numeric). Ecco una completa (e molto più breve) esempio virgola che non ha bisogno di spinta:

std::vector<double> result(10); 
std::iota(result.begin(), result.end(), 0.0); 
std::cout << "result: "; 
std::copy(result.begin(), result.end(), std::ostream_iterator<double>(std::cout, ", ")); 

Grazie, sehe, per segnalarlo.

2

cosa ha detto Phil;

Tuttavia, in questo caso, si potrebbe fare molto più semplice utilizzando the iota algorithm:

#include <vector> 
#include <boost/range/algorithm_ext.hpp> 

int main() { 
    std::vector<double> result(10); 
    boost::iota(result, 0); 
} 
Problemi correlati