Reputation: 1937
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]
Upvotes: 3
Views: 195
Reputation: 66230
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.
Upvotes: 1