I have a program that creates a JSON file using json-glib for ReST Server. The file has 2 field namely id and value. id is only std::string but value can be an integer, a boolean, a string (through std::string od char const *) or a floating point, depending on the value to be transmitted. I have trouble in c.str() function and char *.
if(std::is_integral<T>::value)
{
if(std::is_same<T, bool>::value)
{
if(json_builder_add_boolean_value (builder, tagValue) == nullptr)
{
returnMessage = string("json_builder_add_boolean_value was inconsistent in setTag(Boolean). TagName : ") + tagName + string("TagValue : ") + to_string(tagValue);
#ifdef __DEBUG
cerr << returnMessage;
#endif
return false;
}
}
else
{
if(json_builder_add_int_value (builder, tagValue) == nullptr)
{
returnMessage = string("json_builder_add_int_value was inconsistent in setTag(Int). TagName : ") + tagName + string("TagValue : ") + to_string(tagValue);
#ifdef __DEBUG
cerr << returnMessage;
#endif
return false;
}
}
}
else if(std::is_floating_point<T>::value)
{
if(json_builder_add_double_value (builder, tagValue) == nullptr)
{
returnMessage = string("json_builder_add_double_value was inconsistent in setTag(Double). TagName : ") + tagName + string("TagValue : ") + to_string(tagValue);
#ifdef __DEBUG
cerr << returnMessage;
#endif
return false;
}
}
else if(std::is_same<T, string>::value or std::is_same<T, const string>::value)
{
if(json_builder_add_string_value (builder, tagValue.c_str()) == nullptr)
{
returnMessage = string("json_builder_add_string_value was inconsistent in setTag(String). TagName : ") + tagName + string("TagValue : ") + to_string(tagValue);
#ifdef __DEBUG
cerr << returnMessage;
#endif
return false;
}
}
else if(std::is_same<T, char *>::value or std::is_same<T, const char *>::value)
{
if(json_builder_add_string_value (builder, tagValue) == nullptr)
{
returnMessage = string("json_builder_add_string_value was inconsistent in setTag(String). TagName : ") + tagName + string("TagValue : ") + to_string(tagValue);
#ifdef __DEBUG
cerr << returnMessage;
#endif
return false;
}
}
error: request for member ‘c_str’ in ‘tagValue’, which is of non-class type ‘int’ if(json_builder_add_string_value (builder, tagValue.c_str()) == nullptr)
error: invalid conversion from ‘int’ to ‘const gchar* {aka const char*}’ [-fpermissive]
I'm using C++14
It's a pity.
You can't use if constexpr that is the natural solution for your problem but it's introduced from C++17.
Anyway, without if constexpr, the compiler must compile every part of your function; so if your tagValue is a bool, the compiler must compile also the tagValue.c_str() call that isn't available for a bool.
So the error.
Pre C++17 you have to develop different function for different types.
A possible solution is use overloading and SFINAE defining three not-template foo() functions for the three exact types (bool, std::string const & and char const *)
void foo (std::string const & id, bool value)
{
// json_builder_add_boolean_value, etc
std::cout << "-- bool case: " << id << ", " << value << std::endl;
}
void foo (std::string const & id, std::string const & value)
{
// json_builder_add_string_value, etc
std::cout << "-- std::string case: " << id << ", " << value << std::endl;
}
void foo (std::string const & id, char const * value)
{
// json_builder_add_string_value, etc
std::cout << "-- char * case: " << id << ", " << value << std::endl;
}
and two template foo() functions, enabled through SFINAE for integral types (the first one) and for floating point types (the second one)
template <typename T>
std::enable_if_t<std::is_integral<T>{}>
foo (std::string const & id, T const & value)
{
// json_builder_add_int_value, etc
std::cout << "-- integral case: " << id << ", " << value << std::endl;
}
template <typename T>
std::enable_if_t<std::is_floating_point<T>{}>
foo (std::string const & id, T const & value)
{
// json_builder_add_double_value, etc
std::cout << "-- floating case: " << id << ", " << value << std::endl;
}
so calling
foo("1", false);
foo("2", 0L);
foo("3", 0.0f);
foo("4", std::string{"zero"});
foo("5", "zero");
you get
-- bool case: 1, 0
-- integral case: 2, 0
-- floating case: 3, 0
-- std::string case: 4, zero
-- char * case: 5, zero
Observe that bool is an integral type, so can match the foo() template integral version and the foo() bool specific version.
In this case is preferred the exact match, so the bool specific version is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With