lex_cast:格式化流,未格式化

我曾经在下面看到这个漂亮的小代码片段,在这里:
template<typename to_t, typename from_t>
to_t lex_cast(const from_t &arg) {
    to_t ret;
    std::stringstream os;
    os << arg;
    os >> ret;
    return ret;
}
这模仿boost :: lexical_cast。用法:
string tmp = ::lex_cast<string>(3.14);
但是,由于格式化流的默认跳过,以下内容将无法按预期工作:
string tmp = ::lex_cast<string>("foo bar"); // will only return foo, but I want entire string
(我期待与 n的类似问题)。 我试图设置noskipws和模板专业化但无济于事。请指教。     
已邀请:
实际上,要涵盖从字符串转换为字符串的所有可能情况,您需要一个相当复杂的机制。我已经在下面粘贴了一个可能的实现,但这确实留下了为什么你不想使用
boost::lexical_cast
的问题。
//Beware, brain-compiled code ahead!
namespace detail {
    template< typename T, typename S >
    struct my_lexical_caster {
        static T my_lexical_cast(const S& s) {
            std::stringstream ss;
            if( !(ss << s) ) throw std::bad_cast("cannot stream from source");
            T t;
            if( !(ss >> t) ) throw std::bad_cast("cannot stream to target");
            return t;
        }
    };    
    template< typename S >
    struct my_lexical_caster<std::string,S> {
        static std::string my_lexical_cast(const S& s) {
            std::ostringstream oss;
            if( !(oss << s) ) throw std::bad_cast("cannot stream from source");
            return oss.str();
        }
    };
    template< typename T >
    struct my_lexical_caster<T,std::string> {
        static T my_lexical_cast(const std::string& s) {
            std::stringstream ss(s);
            T t;
            if( !(ss >> t) ) throw std::bad_cast("cannot stream to target");
            return t;
        }
    };
    template< typename T >
    struct my_lexical_caster<T,T> {
        static const T& my_lexical_cast(const T& s) {return s;}
    };
    template<>
    struct my_lexical_caster<std::string,std::string> {
        static const std::string& my_lexical_cast(const std::string& s) {return s;}
    };
}

template< typename T, typename S >
inline T my_lexical_cast(const S& s)
{
    return detail::my_lexical_caster<T,S>::my_lexical_cast(s);
}
那么为什么这么复杂呢? 首先,看看我们在这里有两个模板参数,其中一个参数决定了
my_lexical_cast<>()
的返回类型。现在我们必须为某些特殊类型提供特殊实现。虽然我们可以基于不同的函数参数重载函数,但我们不能基于返回值重载它们。因此,我们需要专门化模板,而不是重载功能模板。 但是,这也带来了一个问题:功能模板没有部分专业化,只有完全专业化。通常给出的原因是,我们有功能模板的重载,而不是功能模板部分特化。虽然这可能是,但是当涉及到返回类型时,它对我们没有帮助。 规避缺失函数模板部分特化的常用方法是使用_class模板部分特化,因为它是可用的。这是通过创建类模板并在其公共静态成员函数中实现算法来完成的。然后,类模板可以是部分专用的,并且每个特化可以具有其自己的静态成员函数的实现。 因此,这解释了为什么在
detail
命名空间中存在类模板(实际上它们是结构体,但这只是为了节省我们明确地将其唯一成员公开的麻烦)。 为什么我们需要这么多的专业化? 嗯,首先,肯定需要一个通用的实现,从任何可流式转换为任何其他类型。 然后,正如您所观察到的,我们需要一个专门化来涵盖我们想要转换为字符串的情况,因为在这种情况下默认实现是错误的。 与两个模板参数属于同一类型的情况相匹配的是纯优化:如果要将
int
转换为
int
,我们可以分发原始值。你可能会问自己为什么有人想要这样做,但在模板代码中,人们不知道代码可能被调用的类型,这样的事情总是发生。 从字符串转换为任何其他类型的专业化也是一种优化。它避免了将字符串流式传输到流中,而是直接初始化输出字符串流。这假设后者实际上比前者更快。虽然我没有测量过这个,但我认为我们可以放心地认为它永远不会慢。 留下最后一个,将一个字符串“转换”为一个字符串。为什么我们需要这个,是不是已经涵盖了“转换”和
T
T
的情况?嗯,是的,它是,我们也可以使用这个,因为从语义上讲,它做的是正确的。但是编译器并不关心语义,它唯一关心的是语法。当你想将一个convert11ѭ“转换”成一个
std::string
时,编译器会找到三个部分匹配的特化:
<T,std::string>
<std::string,T
<T,T>
。由于它不知道在这种情况下该做什么并引发错误,我们需要通过提供比这三者中的任何一个更加一致的匹配来帮助它。     

要回复问题请先登录注册