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

时间:2018-08-30 13:51:26

标签: c++

我正在创建自己的lexical_cast函数来包装Boost函数,并具有bool类型的特殊行为,并且还要避免Boost的词法转换函数的异常版本。

我完全专门研究bool的功能,以便可以将iostream用于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中的测试中的第4种情况不应为“通用转换”,而应使用C字符串特殊化。

我觉得我在这里陷入模板混乱的困境,对于看似简单的事情,解决方案迅速变得混乱和复杂。我要做什么的理想解决方案是什么?我如何使布尔专业化工作正常?

编辑

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

第二,我意识到也可以使用重载,但是我不允许在不指定返回类型的模板参数的情况下使用lexical_cast的情况。例如,我必须做lexical_cast<bool>("true"),我不能做lexical_cast("true")。我的目标是保持与boost::lexical_cast的接口兼容,在这种情况下,没有可以忽略template参数的情况。

由于调用lexical_cast时必须使用模板语法,因此我不得不使用全部功能的专业化知识。

2 个答案:

答案 0 :(得分:4)

您必须记住,字符串文字实际上是const个字符的数组

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

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

请不要忘记大小N包含空终止符。

答案 1 :(得分:2)

由于这里每个人的调查,激发了我一些想法,我认为我找到了令人满意的解决方案。关键是使用模板替代,这是该线程中其他人的提示。感谢大家的帮助。解决方法如下:

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