首页 > 解决方案 > 返回流运算符的代理类时解包参数

问题描述

我正在尝试使用流运算符实现以下行为:

std::cout << print(42, "foo", 'c', 2.0);

这是流操作符代理类的实现:

template <typename T>
class StreamProxy {
  std::function<std::ostream &(std::ostream &, T)> m_func;
  T m_arg;

 public:
  StreamProxy(std::function<std::ostream &(std::ostream &, T)> f, T arg)
      : m_func(f), m_arg(arg) {}
  inline void do_op(std::ostream &str) const { m_func(str, m_arg); }
};

template <typename T>
inline std::ostream &operator<<(std::ostream &os, StreamProxy<T> const &m) {
  if (!os.good()) return os;
  m.do_op(os);
  return os;
}

template <typename T>
class Print : public StreamProxy<T const &> {
  inline static std::ostream &call(std::ostream &os, T const &v) {
    os << v;
    return os;
  }

 public:
  inline Print(T const &v) : StreamProxy<T const &>(call, v) {}
};

到目前为止,我只得到了基本案例,我正在努力解压参数:

template <typename T>
inline auto print(T const &v) {
  return Print<T>(v);
}

template <typename T, typename... Args>
inline auto print(T const &v, Args &&... args) {

  // NOTE: As pointed out by  Davis Herring, the usage of stream operator here doesn't make sense.
  return print(v) << print(args...); // This will fail!
}

如何使用参数包来实现?下面的错误消息似乎颇具误导性。

/home/me/Projects/ostr/include/ostr.hpp:62: error: no match for ‘operator<<’ (operand types are ‘Print<char [14]>’ and ‘Print<int>’)
   return print(v) << print(args...);
          ~~~~~~~~~^~~~~~~~~~~~~~~~~

标签: c++c++17variadic-templates

解决方案


在我看来,您使问题过于复杂,并且您将可变参数解包放置在错误的位置(在流不可用的情况下使用流运算符)。

在我看来,捕获 lambda 函数中的参数并使用std::ostream.

我的意思是……如下

#include <iostream>
#include <functional>

struct foo
 {
   std::function<std::ostream & (std::ostream &)> l;

   template <typename ... As>
   foo (As && ... as)
     : l{[&as...](std::ostream & os) -> std::ostream &
         { return ((os << std::forward<As>(as)), ...); }}
    { } 
 };

std::ostream & operator<< (std::ostream &os, foo const & f)
 { return os.good() ? f.l(os) : os; }

template <typename ... As>
foo print (As &&... as)
 { return { std::forward<As>(as)... }; }

int main ()
 {
   std::cout << print(42, "foo", 'c', 2.0);
 }

推荐阅读