2014-11-06 3 views
0

я взял код здесь:Invalid Static Cast

http://en.wikipedia.org/wiki/Variadic_template

Однако он рассматривает uint8_t и int8_t, как ASCII и поэтому я хочу, чтобы бросить все, что в int16_t. Я пытался сделать это:

template<typename T, typename... Args> 
void log(const char *s, T value1, Args... args) 
{ 
while (*s) { 
    if (*s == '%') { 
     if (*(s + 1) == '%') { 
      ++s; 
     } 
     else { 

     if (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value) 
     { 
      int16_t x = value1; 
      int16_t x = static_cast<int16_t>(value1); 
      std::cout << x; 
     } 
     else 
     { 
      std::cout << value1; 
     } 

      log(s + 1, args...); // call even when *s == 0 to detect extra arguments 
      return; 
     } 
    } 
    std::cout << *s++; 
} 
throw std::logic_error("extra arguments provided to printf"); 
} 

Однако я получил ошибку:

error: invalid static_cast from type ‘std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >’ to type ‘int16_t’ 

есть в любом случае, чтобы не печатать ASCII?

+1

Проблема я вижу в том, что 'x' дважды объявлен. – gsamaras

+0

Это два пути, которые я пытался использовать. Просто играю. Ошибка описана. Он не будет компилироваться. – user1876942

+0

Ну код, который у вас есть в вашем вопросе, будет скомпилирован для меня, если имя второй 'x' как' x1'. – gsamaras

ответ

2

Проблема:

Как ваш компилятор сказал:

error: invalid static_cast from type ‘std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >’ to type ‘int16_t’ 

Я полагаю, ваш позвонив функцию журнала, как это:

log("my % thing %....", /*my std::string*/ stringToto, 5,/*....*/); 

И есть проблема!

Когда компилятор видит, что вы хотите static_cast a std::stringint16_t, он генерирует ошибку!

То, что вы сделали неправильно

Эта часть:

if (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value) 
    { 
     int16_t x = value1; 
     int16_t x = static_cast<int16_t>(value1); 
     std::cout << x; 
    } 
    else 
    { 
     std::cout << value1; 
    } 

Почему? На самом деле, даже если условие (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value) ложно, компилятор будет интерпретировать ваш static_cast

Что вы должны сделать

Используйте функцию, которая получит аргумент (независимо от того является его тип) и генерировать зЬй :: строка, как это:

template<typename T> 
std::string 
my_to_string(T) { return ("what is this type?"); } 

template<> 
std::string 
my_to_string(std::string s) { return (s); } 

template<> 
std::string 
my_to_string(int integer) { return (std::to_string(integer)); } 

, а затем вызвать его в лог-функции, как это: станд :: соиЬ < < my_to_string (значение1);

Удача, улучшающая вашу работу!

+0

Да, некоторые из моих значений являются строками. Я забыл о них. Благодарю. Я сделаю это. – user1876942

3

If-statements не принимает решений во время компиляции; компилятор всегда проверяет обе ветви.

Вам необходимо создать перегруженную функцию write(), где потоки версии по умолчанию для cout и которые вы можете перегрузить для определенных типов (например, char).

+0

Или надейтесь, что оптимизатор устранит одну из ветвей ... не самый надежный способ писать код. –

+0

@SanderDeDycker Нет, это не помогает, если одна из ветвей имеет недопустимый код в конкретном экземпляре. Если беспокоиться о том, что мертвая ветка находится в результирующем коде, полагаться на оптимизатор отлично. –

+0

Afaik, который зависит от компилятора (что является одной из причин, по которым я сказал, что это не очень надежно). Я не думаю, что стандарт C++ предполагает, что мертвый код должен быть чем-то большим, чем синтаксически правильным (по сравнению с семантически правильным). Но тогда вы, вероятно, правы, что на практике большинство компиляторов будут обеспечивать соблюдение обоих из-за того, как они создают дерево разбора. –

1

Вы, кажется, называете свою функцию std::string, которая не может быть преобразована в int16_t. Вместо static_cast, вы можете использовать следующий шаблон функции, которая перегружается для строк:

template<typename T> 
auto cast_to_int(T const& t) -> int16_t 
{ 
    return static_cast<int16_t>(t); 
} 

auto cast_to_int(std::string const& t) -> int16_t 
{ 
    std::istringstream ss(Text); 
    int16_t result; 
    ss >> result; 
    return result; 
} 

В конце концов, вы должны перегрузить его для дальнейших типов.


Вызов выше через

std::cout<< cast_to_int(value1); 

вместо целого блока

if (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value) 
    { 
     int16_t x = value1; 
     int16_t x = static_cast<int16_t>(value1); 
     std::cout << x; 
    } 
    else 
    { 
     std::cout << value1; 
    } 
Смежные вопросы