简体   繁体   中英

C++ std::any function that convert std::any of C char-array to string

#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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM