2015-07-10 10 views
5

Poniższy kod:Jak użyć wyraźnego rzutowania, aby ukryć to ostrzeżenie?

#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)); 
} 

generuje ostrzeżenie (i ponad 100 wierszy matrycy śladu stosu wywołań):

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 

Chcę poinformować kompilator, że nie obchodzi, że moja int64_t są konwertowane na double. Ja też nie chcę używać 32-bitowej int. Zwykle używam static_cast<double>(my64BitInt) do rozwiązania tego problemu, ale to nie zadziała dla zakresu. W tej chwili używam kompilator pragmy, aby wyłączyć ostrzeżenie, ale to nie jest idealne.

Edytuj: Oto pastebin z pełnym wyjściem kompilatora.

+0

1) Można wyłączyć ostrzeżenia w ustawieniach projektu zamiast z pragma, jeśli uważasz, że nigdy nie dba o to. 2) Dlaczego 'first' i' last' są zadeklarowane jako 'int64_t' zamiast' double'? – celticminstrel

+0

@celticminstrel pragmas w Visual Studio pozwala ci na zignorowanie ostrzeżenia na poszczególnych liniach kodu i pozostawienie ich na miejscu dla reszty projektu. – IronMensan

+0

Jestem świadomy. (Możesz to zrobić również za pomocą clang/gcc, choć składnia jest trochę inna.) Po prostu wskazywałem to częściowo, ponieważ osobiście uważam, że to ostrzeżenie jest bezużyteczne częściej niż użyteczne i częściowo na wypadek, gdybyś się zgodził. – celticminstrel

Odpowiedz

2

Myślę, że będziesz musiał użyć std::transform zamiast boost_range. Ponadto wolę używać boost numeric cast nad wbudowanym static_cast.

Oto przykład roboczych:

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, ", ")); 

} 

Powyższy kod używa transform z funktora Convert. Jeśli wolisz lambda, to działa (i jest bardziej zwięzły) za:

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

EDIT Dodaj wariant jota zbyt

Jak sehe zwraca uwagę, aby wygenerować wektor deblu w przedziale [0 , 10), możesz użyć funkcji std library iota (od #include numeric). Powyżej znajduje się pełna (i znacznie krótszy) przykład jota, że ​​nie potrzebuje doładowania:

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, ", ")); 

Dziękuję sehe, za wskazanie go.

2

co Phil powiedział;

Jednak w tym przypadku, można zrobić dużo prostsze przy użyciu the iota algorithm:

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

int main() { 
    std::vector<double> result(10); 
    boost::iota(result, 0); 
} 
Powiązane problemy