为流运算符返回代理 class 时解包参数

Unpacking parameters when returning a proxy class for stream operator

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

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

这是stream operator proxy的实现class:

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...);
          ~~~~~~~~~^~~~~~~~~~~~~~~~~

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

在我看来,在 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);
 }