user1876942
user1876942

Reputation: 1501

Invalid Static Cast

I have taken code from here:

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

However it treats uint8_t and int8_t as ASCII and so I want to cast anything that is to int16_t. I tried to do this:

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

However I got the error:

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

Is there anyway not to print out ASCII?

Upvotes: 0

Views: 4914

Answers (3)

davidhigh
davidhigh

Reputation: 15528

You seem to call your function with a std::string, which cannot be converted to int16_t. Instead of the static_cast, you could use the following function template which is overloaded for strings:

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

Eventually, you have to overload it for further types.


Call the above via

std::cout<< cast_to_int(value1);

instead of the whole block

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

Upvotes: 2

CollioTV
CollioTV

Reputation: 686

The problem:

Like your compiler said:

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

I suppose your calling your log function like this:

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

And there is the problem!

When the compiler see you want to static_cast a std::string to a int16_t it generate an error!

What you've done wrong

This part:

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

Why? In fact, even if your condition (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value) is false, your compiler will interpret your static_cast

What should you do

Use a function that get an argument (whatever is its type) and generate an std::string, like this:

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

and then call it in your log function like this: std::cout << my_to_string(value1);

Good Luck improving your work!

Upvotes: 2

Sebastian Redl
Sebastian Redl

Reputation: 72062

If-statements don't make compile-time decisions; the compiler will always check both branches.

You need to create an overloaded write() function, where the default version streams to cout, and which you can overload for specific types (such as char).

Upvotes: 3

Related Questions