代码之家  ›  专栏  ›  技术社区  ›  void.pointer

无法完全专门化字符串文本的模板

c++
  •  5
  • void.pointer  · 技术社区  · 6 年前

    我在创造我自己的 lexical_cast 包装Boost的函数,具有 bool 类型,还可以避免Boost词法转换函数的异常版本。

    我完全专精于 布尔 这样我就可以用iostreams std::boolalpha 操纵器。但是,我不能让它为字符串文本工作。下面是完整的代码,还有一个指向实时示例的链接:

    template<typename T1, typename T2>
    T1 lexical_cast(T2 const& value, T1 const& defaultValue = T1{})
    {
        std::cout << "Generic Conversion\n";
        T1 convertedValue;
        if (!boost::conversion::try_lexical_convert(value, convertedValue))
        {
           return defaultValue;
        }
    
        return convertedValue;
    }
    
    template<>
    bool lexical_cast<bool, char const*>(char const* const& value, bool const& defaultValue)
    {
        std::cout << "Specialized c string to bool\n";
        bool convertedValue;
        std::istringstream ss(value);
        if (!(ss >> std::boolalpha >> convertedValue))
        {
            std::cout << "Failed string to bool\n";
            return defaultValue;
        }
    
        return convertedValue;
    }
    
    template<>
    bool lexical_cast<bool, std::string>(std::string const& value, bool const& defaultValue)
    {
        std::cout << "Specialized string to bool\n";
        return lexical_cast<bool>(value.c_str(), defaultValue);
    }
    
    template<>
    std::string lexical_cast<std::string, bool>(bool const& value, std::string const& defaultValue)
    {
        std::cout << "Specialized bool to string\n";
        std::ostringstream ss;
        if (!(ss << std::boolalpha << value))
        {
            std::cout << "Failed bool to string\n";
            return defaultValue;
        }
    
        return ss.str();
    }
    
    int main()
    {
        lexical_cast<std::string>(3.14f);
        lexical_cast<float>("3.14");
        lexical_cast<int>("3.14");
        lexical_cast<bool>("true");
        lexical_cast<std::string>(true);
    }
    

    Live Sample

    Generic Conversion
    Generic Conversion
    Generic Conversion
    Generic Conversion
    Specialized bool to string
    

    第四个案例 main 上面不应该是“泛型转换”,它应该使用C字符串专门化。

    我觉得我在这里就像掉进了一个充满模板污点的兔子洞,解决方案很快就变得扑朔迷离&对于一些看似简单的东西来说很复杂。对于我正在尝试做的事情,理想的解决方案是什么?如何让bool专业化按我的意愿工作?

    编辑

    对需求的澄清:我理解字符串文字实际上是字符数组。在我上面的例子中,我尝试了 char* 无论如何,因为接受char数组需要另一个非类型模板参数,我马上就知道我不能使用这个参数,因为它需要部分地专门化我的函数模板,这是非法的。

    其次,我意识到也可以使用重载,但我不能允许 词汇转换 lexical_cast<bool>("true") ,我做不到 lexical_cast("true") boost::lexical_cast ,不存在可以省略模板参数的情况。

    词汇转换

    2 回复  |  直到 6 年前
        1
  •  4
  •   Some programmer dude    6 年前

    你必须记住字符串文字实际上是 数组 const 角色。

    让函数接受字符串文字的正确方法如下:

    template<size_t N>
    void function(char const (&string)[N]);
    

    N 包括空终止符。

        2
  •  2
  •   void.pointer    6 年前

    template<typename T1, typename T2>
    T1 lexical_cast(T2 const& value, T1 const& defaultValue = T1{})
    {
        std::cout << "Generic Conversion\n";
        T1 convertedValue;
        if (!boost::conversion::try_lexical_convert(value, convertedValue))
        {
           return defaultValue;
        }
    
        return convertedValue;
    }
    
    template<>
    std::string lexical_cast<std::string, bool>(bool const& value, std::string const& defaultValue)
    {
        std::cout << "Specialized bool to string\n";
        std::ostringstream ss;
        if (!(ss << std::boolalpha << value))
        {
            std::cout << "Failed bool to string\n";
            return defaultValue;
        }
    
        return ss.str();
    }
    
    template<typename B>
    std::enable_if_t<std::is_same<B, bool>::value, B>
    lexical_cast(char const* value, bool defaultValue = {})
    {
        std::cout << "Specialized c string to bool\n";
        bool convertedValue;
        std::istringstream ss(value);
        if (!(ss >> std::boolalpha >> convertedValue))
        {
            std::cout << "Failed string to bool\n";
            return defaultValue;
        }
    
        return convertedValue;
    }
    
    template<typename B>
    std::enable_if_t<std::is_same<B, bool>::value, B>
    lexical_cast(std::string const& value, bool defaultValue = {})
    {
        std::cout << "Specialized string to bool\n";
        return lexical_cast<bool>(value.c_str(), defaultValue);
    }
    
    template<typename T>
    void PrintResult(T const& result)
    {
        std::cout << "--- Result: " << result << "\n";
    }
    
    int main()
    {
        PrintResult(lexical_cast<std::string>(3.14f));
        PrintResult(lexical_cast<float>("3.14"));
        PrintResult(lexical_cast<int>("3.14"));
        PrintResult(lexical_cast<bool>("true"));
        PrintResult(lexical_cast<std::string>(true));
    
        std::string trueString = "true";
        PrintResult(lexical_cast<bool>(trueString));
    }
    

    输出:

    Generic Conversion
    --- Result: 3.1400001
    Generic Conversion
    --- Result: 3.14
    Generic Conversion
    --- Result: 0
    Specialized c string to bool
    --- Result: 1
    Specialized bool to string
    --- Result: true
    Specialized string to bool
    Specialized c string to bool
    --- Result: 1
    

    live sample here .