【问题标题】:Converting Tuple to string将元组转换为字符串
【发布时间】:2014-05-02 20:28:22
【问题描述】:

自从我发现boost::lexical_cast 以来,所有的转换都是轻而易举的事。直到尝试将元组元素转换为字符串。像Int2StringDouble2String 我想要一种从任意数量元素的元组生成单个字符串的方法

由于转换的主题具有任意(但编译时间已知)维度,在some research 之后,我查看了boost::fusion 并找到了这个解决方案:

#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <boost/fusion/include/for_each.hpp>

template <class Sequence>
std::string StringFromSequence(const Sequence &seq) 
{
    std::string result;
    boost::fusion::for_each(seq, toString(result));
    return result;
}

toString 是一个函子,将词法转换应用于被调用的对象:

struct toString: boost::noncopyable 
{
    explicit toString(std::string& res) : result(res)
    {
    }
    template <class T>
    void operator()(const T& v) 
    {
        result += boost::lexical_cast<std::string>(v);
    }
private:
    std::string &result;
};

当尝试使用它时

std::tuple<int, char, double> tup{ 1, 'a', 2.2 };
toString(tup);

我得到一个编译错误

错误 C2893:无法专门化函数模板 'enable_if, void>::type boost::fusion::for_each(const Sequence &,const F &)'

  1. 有人能发现并纠正错误吗?
  2. 是否有任何(也许是免费的)替代品? (这需要编译时递归,我希望尽量避免所有样板代码)

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    由于这个问题被标记为 C++11,我的看法如下:

    #include <iostream>
    #include <string>
    #include <tuple>
    
    template<typename T, T...>
    struct integer_sequence { };
    
    template<std::size_t N, std::size_t... I>
    struct gen_indices : gen_indices<(N - 1), (N - 1), I...> { };
    template<std::size_t... I>
    struct gen_indices<0, I...> : integer_sequence<std::size_t, I...> { };
    
    template<typename H>
    std::string& to_string_impl(std::string& s, H&& h)
    {
      using std::to_string;
      s += to_string(std::forward<H>(h));
      return s;
    }
    
    template<typename H, typename... T>
    std::string& to_string_impl(std::string& s, H&& h, T&&... t)
    {
      using std::to_string;
      s += to_string(std::forward<H>(h));
      return to_string_impl(s, std::forward<T>(t)...);
    }
    
    template<typename... T, std::size_t... I>
    std::string to_string(const std::tuple<T...>& tup, integer_sequence<std::size_t, I...>)
    {
      std::string result;
      int ctx[] = { (to_string_impl(result, std::get<I>(tup)...), 0), 0 };
      (void)ctx;
      return result;
    }
    
    template<typename... T>
    std::string to_string(const std::tuple<T...>& tup)
    {
      return to_string(tup, gen_indices<sizeof...(T)>{});
    }
    
    int main(int argc, char** argv)
    {
      std::tuple<int, double, float> tup(1, 2.1, 3.2);
      std::cout << to_string(tup) << std::endl;
    }
    

    如果您想坚持使用 boost::lexical_cast,请将 to_string 替换为 lexical_cast。

    ideone 上的实时输出

    【讨论】:

      【解决方案2】:

      抱歉,我懒得详细说明你犯错的地方,但这里有一个使用 fusion 和 C++14 多态 lambda 的解决方案:

      #include <tuple>
      #include <string>
      #include <iostream>
      #include <boost/lexical_cast.hpp>
      #include <boost/fusion/adapted/std_tuple.hpp> // you're missing this huh? it's needed to use fusion with std::tuple
      #include <boost/fusion/algorithm/iteration/for_each.hpp>
      
      int main() {
          using namespace std;
          using namespace boost::fusion;
      
          string result;
          for_each(make_tuple(1, 'a', 2.2), [&result](auto &s) {
              result += boost::lexical_cast<string>(s) + ' ';
          });
      
          cout << result << endl;
      }
      

      http://coliru.stacked-crooked.com/a/f110238a317eede9

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-30
        • 2012-01-19
        • 2016-03-14
        • 2017-06-27
        • 2013-11-07
        相关资源
        最近更新 更多