C++将简单值转换为字符串

Fer*_*eak 22 c++ stringstream string-conversion c++11

现在我用下面的一段代码dummily转换基本类型(int,long,char[],这种东西),以std::string进行进一步的处理:

template<class T>
constexpr std::string stringify(const T& t)
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}
Run Code Online (Sandbox Code Playgroud)

但是我不喜欢它依赖的事实std::stringstream.我尝试使用std::to_string(来自C++ 11的保留节目)然而它会扼杀char[]变量.

有一种简单的方法可以为这个问题提供优雅的解决方案吗?

cer*_*wny 10

据我所知,这样做的唯一方法是通过SFINAE参数类型对模板进行专门化.

您需要包含type_traits.

所以代替你的代码使用这样的东西:

template<class T>
 typename std::enable_if<std::is_fundamental<T>::value, std::string>::type stringify(const T& t)
  {
    return std::to_string(t);
  }

template<class T>
  typename std::enable_if<!std::is_fundamental<T>::value, std::string>::type  stringify(const T& t)
  {
    return std::string(t);
  }
Run Code Online (Sandbox Code Playgroud)

这个测试对我有用:

int main()
{
  std::cout << stringify(3.0f);
  std::cout << stringify("Asdf");
}
Run Code Online (Sandbox Code Playgroud)

重要说明:传递给此函数的char数组需要以null结尾!

如yakk的评论中所述,您可以通过以下方式摆脱空终止:

template<size_t N> std::string stringify( char(const& s)[N] ) { 
    if (N && !s[N-1]) return {s, s+N-1};
    else return {s, s+N}; 
}
Run Code Online (Sandbox Code Playgroud)

  • @black我的回答将处理这个问题.你只需要调整一下`enable_if`并添加`ostringstream`. (2认同)
  • `constexpr`在这个答案中没有意义,因为`std :: string`不是[literal type](http://en.cppreference.com/w/cpp/concept/LiteralType).这里有更严重的缺陷.有关详细信息,请参阅[我的回答](http://stackoverflow.com/a/30276624/2266855). (2认同)

utn*_*tim 9

有一种简单的方法可以为这个问题提供优雅的解决方案吗?

由于没有人提出它,考虑使用boost :: lexical_cast.

这与实现std :: ostream << operator的任何内容无缝集成,并且可以扩展为自定义类型.

  • 我之前已经发现了这一点:人们倾向于认为对某个对象有依赖关系,不知何故会使代码单一/重/资源/慢/丑. (3认同)

Jon*_*Mee 5

我建议使用enable_if_t,如果你要接受任何单个字符变量,你会专注于那些:

template<typename T>
enable_if_t<is_arithmetic<T>::value, string> stringify(T t){
    return to_string(t);
}

template<typename T>
enable_if_t<!is_arithmetic<T>::value, string> stringify(T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}

template<>
string stringify<char>(char t){
    return string(1, t);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我只是专攻char.如果您需要专业化wchar,char16或者char32您也需要这样做.

无论如何对于非算术类型,这些重载将默认使用ostringstream,如果你已经为你的一个类重载了它将处理它的提取操作符,那么这是很好的原因.

对于算术类型,这将使​​用to_string,除了char你重载的任何其他东西,那些可以直接创建一个string.

编辑:

Dyp建议使用是否to_string接受T::type作为我enable_if_t条件的参数.

如果你要访问的最简单的办法是只提供给你is_detected#include <experimental/type_traits>.如果您只是定义:

template<typename T>
using to_string_t = decltype(to_string(declval<T>()));
Run Code Online (Sandbox Code Playgroud)

然后,您可以将代码设置为:

template<typename T>
decltype(to_string(T{})) stringify(T t){
    return to_string(t);
}

template<typename T>
enable_if_t<!experimental::is_detected<to_string_t, T>::value, string> (T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}

template<>
string stringify<char>(char t){
    return string(1, t);
}
Run Code Online (Sandbox Code Playgroud)

我问这个问题,弄清楚如何使用to_string我的条件.如果您无法访问is_detected我强烈建议您阅读一些答案,因为它们非常现象:元编程:函数定义失败定义了单独的函数


bol*_*lov 2

虽然问题不是给我代码类型,但因为我已经实现了一个解决方案,所以我想分享它:

template <class... Tail>
inline auto buildString(std::string const &head, Tail const &... tail)
    -> std::string;

template <class... Tail>
inline auto buildString(char const *head, Tail const &... tail) -> std::string;

template <class... Tail>
inline auto buildString(char *head, Tail const &... tail) -> std::string;

template <class Head, class... Tail>
inline auto buildString(Head const &head, Tail const &... tail) -> std::string;

inline auto buildString() -> std::string { return {}; }

template <class... Tail>
inline auto buildString(std::string const &head, Tail const &... tail)
    -> std::string {
  return head + buildString(tail...);
}
template <class... Tail>
inline auto buildString(char const *head, Tail const &... tail) -> std::string {
  return std::string{head} + buildString(tail...);
}
template <class... Tail>
inline auto buildString(char *head, Tail const &... tail) -> std::string {
  return std::string{head} + buildString(tail...);
}
template <class Head, class... Tail>
inline auto buildString(Head const &head, Tail const &... tail) -> std::string {
  return std::to_string(head) + buildString(tail...);
}
Run Code Online (Sandbox Code Playgroud)

用法:

auto gimmeTheString(std::string const &str) -> void {
  cout << str << endl;
}

int main() {

  std::string cpp_string{"This c++ string"};
  char const c_string[] = "this c string";

  gimmeTheString(buildString("I have some strings: ", cpp_string, " and ",
                             c_string, " and some number ", 24));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

4864 次

最近记录:

10 年,3 月 前