c+中的完全自定义流运算符+; < P> >我想为C++中的我创建一个完全自定义的流管道。

c+中的完全自定义流运算符+; < P> >我想为C++中的我创建一个完全自定义的流管道。,c++,stream,operator-overloading,C++,Stream,Operator Overloading,最终结果应该如下所示: videofilelocation >> preprocessing() >> analyze() >> stabilize() >> video_out(outputfilename).flush(); 因此,preprocessing应该接受输入字符串并加载视频、提取帧等。之后,它应该返回一个自定义结构framevector,该结构应该传递给analyze,依此类推 不幸的是,关于如何实现完全定制的流操作符,没有明确的

最终结果应该如下所示:

videofilelocation >> preprocessing() >> analyze() >> stabilize() >> video_out(outputfilename).flush();
因此,
preprocessing
应该接受输入字符串并加载视频、提取帧等。之后,它应该返回一个自定义结构
framevector
,该结构应该传递给
analyze
,依此类推

不幸的是,关于如何实现完全定制的流操作符,没有明确的教程/解释。(仅适用于
std::ostream
等)

如何做到这一点?

这有助于:

class FileLocation        {};
class PreProcessedData    {};

class PreProcessingAction {
    public:
        PreProcessedData doStuff(FileLocation const& file) const
        {
            return PreProcessedData{};
        }
};

PreProcessingAction preprocessing() {
    return PreProcessingAction{};
}

PreProcessedData operator>>(FileLocation const& file, PreProcessingAction const& action)
{
    return action.doStuff(file);
}

int main()
{
    FileLocation   location;

    location >> preprocessing();
}
老实说,这似乎比帮助更复杂的代码

这样做不是更容易吗:

Data     file            = readData("InputName");
Data     preProcData     = preprocessing(file);
Data     analysedData    = analyze(preProcData);
Data     stabalizedData  = stabilize(analysedData);

Output   output("OutputName");    
output << stabalizedData;
Data file=readData(“InputName”);
数据预处理数据=预处理(文件);
数据分析数据=分析(预处理数据);
数据稳定数据=稳定(分析数据);
输出(“输出名称”);

输出出于好奇,我将此作为谜题,并得到以下小示例:

#include <iostream>
#include <string>

// a sample object which is subject of object stream
struct Object {
  // contents
  std::string name;
  int a, b;
  // constructors.
  Object(int a, int b): a(a), b(b) { }
  Object(const std::string &name, int a, int b):
    name(name), a(a), b(b)
  { }
};

// a functor to initialize an object (alternatively)
struct source {
  Object &obj;
  source(Object &obj, int a, int b): obj(obj)
  {
    this->obj.a = a; this->obj.b = b;
  }
  operator Object& () { return obj; }
};

// a clear functor

struct clear {
  clear() = default;
  Object& operator()(Object &in) const
  {
    in.a = in.b = 0;
    return in;
  }
};

// make clear functor applicable to object "stream"

Object& operator>>(Object &in, const clear &opClear)
{
  return opClear(in);
}

// a global instance

static clear reset;

// an add functor

struct add {
  const int da, db;
  add(int da, int db): da(da), db(db) { }
  Object& operator()(Object &in) const
  {
    in.a += da; in.b += db;
    return in;
  }
};

// make add functor applicable to object "stream"

Object& operator>>(Object &in, const add &opAdd)
{
  return opAdd(in);
}

// a display functor

struct echo {
  const std::string label;
  explicit echo(const std::string &label = std::string()):
    label(label)
  { }
  Object& operator()(Object &in) const
  {
    std::cout << label
      << "Object '" << in.name << "' (" << in.a << ", " << in.b << ")\n";
    return in;
  }
};

// make display functor applicable to object "stream"

Object& operator>>(Object &in, const echo &opEcho)
{
  return opEcho(in);
}

// a sink functor (actually not needed)

struct null {
  null() = default;
  void operator()(Object&) const { }
};

// make echo functor applicable to object "stream"

void operator>>(Object &in, const null &opNull) { opNull(in); }

// check it out:
int main()
{
  Object obj("obj1", 12, 34);
  // either use obj as source
  obj
    >> echo("before add(-2, -4): ")
    >> add(-2, -4)
    >> echo("after add(-2, -4): ")
    >> reset
    >> echo("after reset: ")
    >> null();
  // or a source operator
  source(obj, 11, 22)
    >> echo("before add(11, -11): ")
    >> add(11, -11)
    >> echo("after add(11, -11): ");
  return 0;
}

基本原理受流操作符的启发:

操作符>>
获取一个
对象
引用,处理该对象(更改其状态)并返回引用。这允许通过操作符链传递在表达式最左边参数中创建的对象

为了应用“类似函数的操纵器”,函子类与相应的
操作符>
结合使用

要提供无需
()
即可使用的“操纵器”,还需要一个全局实例

不幸的是,关于如何实现完全定制的流操作符,没有明确的教程/解释

嗯。这是一个短的

运算符>>
是一个二进制运算符。为了使它更灵活,您需要将其编写为一个自由函数重载,这意味着您可以在每个步骤中自定义其含义

为了获得上面的语法,您需要构建一个调用链top
operator>
,这样一个的输出就是下一个的第一个参数

所以
a>>b>>c
的真正意思是:
操作符>>(操作符>>(a,b),c)
注意
a>>b
的输出是
(a>>b)>>c
的第一个输入

下面是一个非常简化的编译链。你会注意到我到处都使用了值语义。如果处理步骤对象是严格的函数对象,则可以通过
const&
传递它们。如果它们携带以前使用的状态,那么您将需要重载
&&
r值引用

#include<fstream>
#include<string>

// a representation of video data
// note-a value type so it will want to own its actual data through a 
// unique_ptr or similar.
struct video_data
{
};

struct preprocessing
{
    void process(video_data&);
};

struct analyze
{
    void process(video_data&);
};

struct stabilize
{
    void process(video_data&);
};

struct video_out
{
    video_out(std::string const& where);
    void process(video_data&);
};

struct flush
{
    void process(video_out&);
};

// now define the interactions
auto operator>>(std::string const& path, preprocessing proc) -> video_data
{
    video_data dat;
    proc.process(dat);
    return dat;
}

auto operator>>(video_data dat, analyze proc) -> video_data
{
    proc.process(dat);
    return dat;
}

auto operator>>(video_data dat, stabilize proc) -> video_data
{
    proc.process(dat);
    return dat;
}

auto operator>>(video_data dat, video_out proc) -> video_out
{
    proc.process(dat);
    return std::move(proc);
}

auto operator>>(video_out dat, flush proc) -> video_out
{
    proc.process(dat);
    return std::move(dat);
}

// now build a chain
int test(std::string const& videofilelocation, std::string const& outputfilename)
{
    videofilelocation >> preprocessing() >> analyze() >> stabilize() >> video_out(outputfilename) >> flush();
} 
#包括
#包括
//视频数据的一种表示形式
//注意—一种值类型,因此它希望通过
//独特的或类似的。
结构视频数据
{
};
结构预处理
{
无效处理(视频和数据);
};
结构分析
{
无效处理(视频和数据);
};
结构稳定
{
无效处理(视频和数据);
};
结构视频输出
{
视频输出(标准::字符串常量和位置);
无效处理(视频和数据);
};
结构刷新
{
无效处理(视频输出和);
};
//现在定义交互
自动运算符>>(标准::字符串常量和路径,预处理过程)->视频数据
{
视频数据;
过程(dat);
返回数据;
}
自动操作员>>(视频数据数据,分析过程)->视频数据
{
过程(dat);
返回数据;
}
自动操作员>>(视频数据数据,稳定程序)->视频数据
{
过程(dat);
返回数据;
}
自动操作员>>(视频数据数据、视频输出过程)->视频输出
{
过程(dat);
返回std::移动(proc);
}
自动操作员>>(视频输出数据,刷新过程)->视频输出
{
过程(dat);
返回标准::移动(dat);
}
//现在建立一个链
int测试(std::string const和videofilelocation,std::string const和outputfilename)
{
视频文件位置>>预处理()>>分析()>>稳定()>>视频输出(输出文件名)>>刷新();
} 

您可以像重载任何其他操作员一样重载它。这应该在C++教科书中描述。一个简单的操作符超载对我的情况不起作用。我没有找到NY帮助它为什么不接受我的输入或下一个流的返回值…注意C++中的约定似乎是管道操作符Aka,因为我正确地理解了管道操作符,它应该被用来操纵数据。不要创建一个流水线的各种步骤,加载,保存文件,创建METS数据等(如果我错了,请纠正我——在现代C++中仍然是NoBee)@ NoSnNote“注意C++中的约定似乎是管道运算符”——当然不是真的。当前的标准库中没有这样使用管道(按位或)操作符的地方。