LuoJi_1995 LuoJi_1995
关注数: 0 粉丝数: 862 发帖数: 29,459 关注贴吧数: 40
发一段代码……用了一下SFINAE pastebin: sT6PjUP3 恩,这里面的内容是可重载的Function的实现,名字叫做Overloads,可以如下使用: struct ifabs_functor { int operator () (int x) { return x > 0 ? x : -x; } double operator () (double x) { return x > 0.0 ? (x == 0.0 ? 0.0 : x) : -x; } }; int abs(int x) { return x > 0 ? x : -x; } double abs(double x) { return x > 0.0 ? (x == 0.0 ? 0.0 : x) : -x; } delegating (abs) multiple_abs; Overloads<int(int), double(double)> ifabs = ifabs_functor(), ifabs2 = multiple_abs; //然后他们就是带有重载版本的function了! 引入了属性模板和ref_pair。 属性模板Property的使用方法: Property<PropertyType, OwnerType, OffsetFunction, Getter, Setter, ConstGetter, ConstSetter>表示类型为PropertyType,所处类型为OwnerType,属性实例的偏移为OffsetFunction(),使用Getter、Setter作为访问器,使用ConstGetter、ConstSetter作为常属性访问器的一个属性。 为了节约空间,使用一个匿名union存储一个类的所有属性。 注意不能把ConstGetter传入Getter作为访问器,虽然这看起来是合理的,但仍需要重载一个非const版本来转发参数。 //e.g. struct Point { private: static int offset_f() { return (int)&((Point *)0xCC)->X - 0xCC; } int x, y; //forwarder int get_x() { return ((const Point *)this)->get_x(); } int get_x() const { return x; } void set_x(const int &value) { x = value; } //forwarder int get_y() { return ((const Point *)this)->get_y(); } int get_y() const { return y; } void set_y(const int &value) { y = value; } public: union { Property<int, Point, offset_f, &Point::get_x, &Point::set_x, &Point::get_x, nullptr> X; Property<int, Point, offset_f, &Point::get_y, &Point::set_y, &Point::get_y, nullptr> Y; }; Point(int xx, int yy) : x(xx), y(yy) { } Point() : x(0), y(0) { } }; /*****blahblahblah*****/ Point p = { 1, 2 }; cout << p.X << ' ' << p.Y << endl; p.X = 10; cout << p.X << ' ' << p.Y << endl; const Point pp = { 1, 2 }; cout << pp.X << ' ' << pp.Y << endl; //pp.X = 123; error: static assertion failed: No Const Setter ref_pair(T)是Overloads<T(), void(const T &)>。 使用ref_pair(T)传递一个引用,这使得可以传递属性的引用,在未来的.GJK中可以用来安全地传递属性保证其主对象不丢失,并且可以直接传递一般对象的引用。 属性模板可以推广到索引器模板(operator []),并且使得传递索引器的引用成为可能(例如传递Map中["David"]的引用)。 这里面使用了SFINAE =wwww=
【constexpr】嗯……share一下如何使constexpr函数可以定义变量 constexpr函数被限定为只能有一个return statement,这是十分不方便的,因为不能定义变量。例如下面的一个情况: constexpr int GetSomeNumber() { return SomeBigConstexprFunc() % 2 == 0 ? SomeBigConstexprFunc() : -1; }//SomeBigConstexprFunc是一个调用起来很耗费时间的东西, //例如深层的很多次重复计算的递归 在g++中,有一些constexpr函数不能被内联,这使得只有编译期计算的不消耗运行时时间,而运行时计算的话,会耗费大量的时间重复运行SomeBigConstexprFunc。 这样,使得我们不得不实现两个版本的GetSomeNumber(constexpr的和非constexpr的),维护成本增加了。 如果有一个变量可以存下这个值呢? 例如如果可以: constexpr int GetSomeNumber() { int tmp = SomeBigConstexprFunc(); return tmp % 2 == 0 ? tmp : -1; } 那么上面的问题完美解决了。很可惜,这是个空想。 下面这个方法可以定义一个变量: constexpr int GetSomeNumber(int tmp = 0) { return (tmp = SomeBigConstexprFunc()) % 2 == 0 ? tmp : -1; } 如果不想让用户以GetSomeNumber(123)来调用的话,很显然可以这样: constexpr int GetSomeNumberInnerImpl(int tmp = 0) { return (tmp = SomeBigConstexprFunc()) % 2 == 0 ? tmp : -1; } constexpr int GetSomeNumber() { return GetSomeNumberInnerImpl(); } 如果需要隐藏GetSomeNumberInnerImpl,则可以进一步将其放入一个类中,作为静态成员函数,然后添加constexpr int GetSomeNumber();为友元,或者直接将GetSomeNumber作为公共静态成员函数。 //不知前人是否有这个方法,有的话我就直接会火星去吧。
一个想法,利用模板……有关正则表达式 std::regex是表示正则表达式的类(我猜是std::basic_regex<char>吧……) 嗯,那么,很明显,regex对表达式的解析是在运行时进行的,这使得我们不能在编译期发现表达式的语法错误,也会降低表达式的匹配速度,因为解析表达式需要时间。 我的想法是:把正则表达式“编译”。 运行时,在构造函数解析表达式,然后用类似下面的结构创造一个正则表达式树: struct IRegex; struct RegexSimpleChar:IRegex; struct RegexCollection:IRegex; struct RegexAnyChar:RegexCollection;//元字符. struct RegexCharToChar:RegexCollection;//[a-z]这样的 struct RegexColl1AndColl2:RegexCollection;//[ac]这样的 struct RegexGreedyRepeat:IRegex;//{least,most}这样的,包括*、?、+ struct RegexNonGreedyRepeat:IRegex;//{least,most}?这样的,包括*?、??、+? //然后各种组啊、或者啊、匹配位置啊之类的 struct regex { regex(string r){/*parse r and construct IRegex*/} match(string r);//innerRegex->Match(r);这样的啦 IRegex *innerRegex; }; 当然这要使用很多虚函数,而且很多很多的function call会变得非常非常非常的慢,估计不如直接用自动机匹配吧? 实际情况是,我们要使用的正则表达式在编译期就确定了,所以是否能在这里优化呢? 我的想法:(可能前人已经有practice了) template <char ch, class TRest> struct RegexSingleChar; template <char ch> struct RegexSingleChar<ch, void>; template <char a, char b, class TRest> struct RegexFromTo;//[a-z] //当然元字符.就表示了RegexFromTo<0, 255, TRest>咯 template <class T1, class T2, class TRest> struct RegexAB; //[acdef]之类的 template <class TToRepeat, class TRest> struct RegexGreedyRepeat; template <class TToRepeat, class TRest> struct RegexNonGreedyRepeat; template <class TRegex> struct CompiledRegex { bool IsMatch(const char *str) { return TRegex::IsMatch(str); } }; 然后写一个preprocessor,把一个形如regex的表达式转换成各种模板的嵌套: regex = string_literal + "regex" string_literal = raw utf16 string literal | utf16 string literal 这样,通过函数的内联,可以省去调用函数的时间,通过模板,可以省去运行时解析正则表达式的时间。 目前我写了一个wildcard的东西,表示个人对正则无力,每次写的时候还得查说明书TAT。 待会放一下wildcard "compiler"的代码……
xNET的Ref的一个问题tuzki->rub_face(); 嗯,最近由于写了一个xNET的translator(吐……)打算进一步改进一下: 将type_name@替换为: 1、在函数体、函数返回值、形式参数、lambda表达式或值类型内,或者是任何类/结构的静态成员,替换为decltype(::xNET::Core::RefOnStack<type_name>),采用引用计数规则。 2、在引用类型中,替换为decltype(::xNET::Core::RefOnHeap<type_name>),这和一般指针很相似,但是不能进行算术运算,并且将创建信息,保存此类型中引用的位置,让GC不产生误判。 主要是想问问大家,对于Ref的分化大家有什么想法……很明显Ref分化让运行时速度加快,但是Ref的分化也带来了几个问题: typedef SomeType@ SomeTypeRef;将是未定义行为 struct SomeThing : Object { Object@ obj; SomeThing() : obj(/*this will be translated into String@*/"hello, world") { } }; //... auto myObj = gcnew<SomeThing>()->obj; 这显然出现了问题 增加替换的时间(要根据上下文信息判断)。 在这里引入“语言”复杂度(是一个整数)的概念,一个“语言”复杂度是所有“语言元素”(例如关键字、标点符号、特殊符号之类的)在不同位置出现的时候其意义种类的平方和。 那么显然引入分化的Ref将会使语言更复杂(你也可以直接使用“晦涩”一词)。 对于判断引用的位置,之前提到过初始化的时候判断一次,之后直接用判断的结果。那么在分化和不分化之间该选择什么呢?(也就是时间复杂度和语言复杂度之间选择……)
简陋版的xNET代码转换器 .GJK在C++语言上做出扩展,使用 type_name@ 表示 decltype(::xNET::Core::Ref<type_name>) 。 例如原来繁杂的 using namespace xNET::Core; Ref<Array<Ref<Object>, 2>> arr = gcnew <Array<Ref<Object>, 2>> (5, 6); //表示一个元素为Ref<Object>的二维数组的xNET引用。 Ref<Array<Ref<Array<Ref<Object>>>>> arr = gcnew <Array<Ref<Array<Ref<Object>>>>>(10); //表示最终元素为Ref<Object>的交错数组的xNET引用。 变成了 using namespace xNET::Core; Array<Objcet@, 2>@ arr = gcnew <Array<Object@, 2>> (5, 6); Array<Array<Objcet@>@>@ arr = gcnew <Array<Array<Object@>@>>(10); 这与C++/CLI中的跟踪句柄或跟踪引用符号^、%很类似。 预计在后续版本中,还可变为 Object@[, ] arr = gcnew <Object@[, ]> (5, 6); Object@[][] arr = gcnew <Object@[][]> (10); //是不是简洁了许多? 这个表示法能且仅能应用于非预处理命令中。注释、字符串中的这种表示不被替换。 支持到的C++0x特性:r"delimiter[]delimiter"形式的raw string。 e.g. 下面代码中 #define SomeTypeRef(Type) Type@ Object@ obj = gcnew <String> ("string@"); /*Conversion from String@ to Object@ is implicit.*/ //只有第二行的第一个@表达法被替换。 使用方法: test1 [/trigraph] [/digraph] files... 将把files...翻译为C++源程序(将替换文件!)。 选项/trigraph和/digraph用于处理三字符和双字符(顺序允许交换),处理方法就是替换掉。 表示这是测试版本,尚不支持unicode等,希望大家帮助多多挑错。 注意:请不要使用奇葩宏(暂时没有做预处理),例如: #define SomeMacro(...) xNET:: SomeMacro(hello; world)String@ str; SomeMacro(hello world)String@ str; #define SomeMacro2() Work(); SomeMacro2()String@ str; 这都会导致不正确的解析。
首页 1 2 3 下一页