Home > Back-end >  C std::any function that convert std::any of C char-array to string
C std::any function that convert std::any of C char-array to string

Time:03-31

#include <iostream>
#include <any>
#include <string>
#include <vector>
#include <map>
using namespace std;

string AnyPrint(const std::any &value)
{   
    cout << size_t(&value) << ", " << value.type().name() << " ";
    if (auto x = std::any_cast<int>(&value)) {
        return "int("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<float>(&value)) {
        return "float("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<double>(&value)) {
        return "double("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<string>(&value)) {
        return "string(\""   (*x)   "\")";
    }
    if (auto x = std::any_cast<char*>(&value)) {
        return string(*x);
    }
}

int main()
{
    int a = 1;
    float b = 2;
    double c = 3;
    string d = "4";
    char *e = "555";
    
    cout << AnyPrint(a) << "\n";
    cout << AnyPrint(b) << "\n";
    cout << AnyPrint(c) << "\n";
    cout << AnyPrint(d) << "\n";
    cout << AnyPrint("555") << "\n";
    cout << AnyPrint(e) << "\n";
    return 0;
}

I'm trying to make a function that converts a std::any object to string, given that the list of possible types is hard-coded. However, there's a problem when user parse raw string like AnyPrint("555"). I use the method from Checking std::any's type without RTTI

I got the following output when I run the program:

140722480985696, i int(1)
140722480985696, f float(2.000000)
140722480985696, d double(3.000000)
140722480985696, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE string("4")
140722480985696, PKc string("4")
140722480985696, Pc 555

How can I handle a std::any of raw string? I don't want to write AnyPrint("555"s) unless it's the only way.

Edit: I use this to run the example https://www.onlinegdb.com/online_c _compiler

CodePudding user response:

Type of "555" is const char[4] which might decays to const char*. You handle char*, but not const char*.

Handling const char* fixes your issue:

std::string AnyPrint(const std::any &value)
{   
    std::cout << size_t(&value) << ", " << value.type().name() << " ";
    if (auto x = std::any_cast<int>(&value)) {
        return "int("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<float>(&value)) {
        return "float("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<double>(&value)) {
        return "double("   std::to_string(*x)   ")";
    }
    if (auto x = std::any_cast<std::string>(&value)) {
        return "string(\""   (*x)   "\")";
    }
    if (auto x = std::any_cast<const char*>(&value)) {
        return *x;
    }
    return "other";
}

Demo

CodePudding user response:

As mentioned in the comments, string literals like "555" are (or decay to) const char* pointers. Your AnyPrint function doesn't handle such an argument type.

Adding the following block fixes the problem:

    if (auto x = std::any_cast<const char*>(&value)) {
        return string(*x);
    }

Also, note that the line, char *e = "555"; is illegal in C ; you need either const char *e = "555"; or char e[] = "555";; using the latter will demonstrate the difference between the char* (with AnyPrint(e)) and const char* (with AnyPrint("555")) types in the std::any_cast<T> blocks.

  • Related