String和Int之间的模板冲突

时间:2018-04-17 12:26:09

标签: c++ templates c++14 sfinae typetraits

我有一个程序,使用json-glib为ReST Server创建一个JSON文件。该文件有2个字段,即idvalueid仅为std::string,但值可以是整数,布尔值,字符串(通过std::string od char const *)或浮点数,具体取决于要传输的值。我在c.str()函数和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;
            }


}
  

错误:请求'tagValue'中的成员'c_str',这是非类型'int'            if(json_builder_add_string_value(builder,tagValue.c_str())== nullptr)

     

错误:从'int'无效转换为'const gchar * {aka const char *}'[-fpermissive]

1 个答案:

答案 0 :(得分:1)

  

我正在使用C ++ 14

很可惜。 您不能使用if constexpr这是您问题的自然解决方案,但它是从C ++ 17中引入的。

无论如何,如果没有if constexpr,编译器必须编译函数的每个部分;因此,如果您的tagValuebool,则编译器还必须编译tagValue.c_str()来自bool的{​​{1}}来电。

所以错误。

Pre C ++ 17你必须为不同的类型开发不同的功能。

一种可能的解决方案是使用重载和SFINAE为三种确切类型定义三个非模板foo()函数(boolstd::string const &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;
 }

和两个模板foo()函数,通过SFINAE为整数类型(第一个)和浮点类型(第二个)启用

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;
 }

所以打电话

   foo("1", false);
   foo("2", 0L);
   foo("3", 0.0f);
   foo("4", std::string{"zero"});
   foo("5", "zero");

你得到了

-- bool case: 1, 0
-- integral case: 2, 0
-- floating case: 3, 0
-- std::string case: 4, zero
-- char * case: 5, zero

观察bool是一个整数类型,因此可以匹配foo()模板整数版本和foo() bool特定版本。

在这种情况下,首选完全匹配,因此调用bool特定版本。