0

I am using RapidJSON to make a message class returned uniformly by http. The code and message field types of the message class are fixed, but the data field type is variable, so I try to use templates...

Since RapidJSON does not automatically convert various JSON types, I write out the basic types separately:

bool intToJson(const std::string& key, int value)
{
    spdlog::info("int: {}", value);
    return true;
}

bool stringToJson(const std::string& key, const std::string& value)
{
    spdlog::info("string: {}", value);
    return true;
}

bool classToJson(const std::string& key, const JsonBase& value)
{
    spdlog::info("class: {}", "");
    return true;
}

message class definition:

template<typename T>
class Message
{
public:
    void toJson();
private:
    T data;
    int code;
    std::string msg;
}

Then use typeid to distinguish the template type in the toJson function, and then use different conversion json functions:

void toJson()
{
    intToJson("code", code);
    stringToJson("message", msg);

    if (typeid(data) == typeid(int))
    {
        intToJson("data", data);
    }
    else if (typeid(data) == typeid(std::string))
    {
        stringToJson("data", data);
    }
    else
    {
        classToJson("data", data);
    }
}

Finally, use it in the main function:

Message<std::string> msg(200, "success", "success");
msg.toJson();

I get an error: cannot convert argument 2 from 'T' to 'int'

what should I do? thank you!!

error C2664: 'bool intToJson(const std::string &,int)' : cannot convert argument 2 from 'T' to 'int'
郭苏莹
  • 15
  • 3
  • Check out [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant) – Caleth May 19 '23 at 12:02
  • You're looking for [`constexpr if`](https://stackoverflow.com/questions/43434491/difference-between-if-constexpr-vs-if]) –  May 19 '23 at 12:04
  • Don't implement it like this. Instead let the compiler find a suitable overload for you. `bool ToJson(const std::string& key, int value) { ... } bool ToJson(const std::string& key, const std::string& value) { ... } ... void toJson() { ... ToJson("data", data); };` You may need to make use of templates+concepts for `ToJson`, if there are implicit conversions that could result in ambiguity... – fabian May 19 '23 at 12:05

2 Answers2

0

If you use overloads, rather than different names, the template is easy:

bool toJson(const std::string& key, int value)
{
    spdlog::info("int: {}", value);
    return true;
}

bool toJson(const std::string& key, const std::string& value)
{
    spdlog::info("string: {}", value);
    return true;
}

bool toJson(const std::string& key, const JsonBase& value)
{
    spdlog::info("class: {}", "");
    return true;
}

template<typename T>
class Message
{
public:
    void toJson();
private:
    T data;
    int code;
    std::string msg;
}

template <typename T>
void Message<T>::toJson()
{
    toJson("code", code);
    toJson("message", msg);
    toJson("data", data);
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
0

With regular if all branches should be valid, even when condition mismatches.

With if constexpr, the discarded branch are not instantiated:

void toJson()
{
    intToJson("code", code);
    stringToJson("message", msg);

    if constexpr (std::is_same_v<T, int>)
    {
        intToJson("data", data);
    }
    else if constexpr (std::is_same_v<T, std::string>)
    {
        stringToJson("data", data);
    }
    else
    {
        classToJson("data", data);
    }
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302