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;
}
基本原理受流操作符的启发:
操作符>>
获取一个对象
引用,处理该对象(更改其状态)并返回引用。这允许通过操作符链传递在表达式最左边参数中创建的对象
为了应用“类似函数的操纵器”,函子类与相应的操作符>
结合使用
要提供无需()
即可使用的“操纵器”,还需要一个全局实例
不幸的是,关于如何实现完全定制的流操作符,没有明确的教程/解释
嗯。这是一个短的
运算符>>
是一个二进制运算符。为了使它更灵活,您需要将其编写为一个自由函数重载,这意味着您可以在每个步骤中自定义其含义
为了获得上面的语法,您需要构建一个调用链topoperator>
,这样一个的输出就是下一个的第一个参数
所以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++中的约定似乎是管道运算符”——当然不是真的。当前的标准库中没有这样使用管道(按位或)操作符的地方。