C++ 非确定性操作的设计模式(非特定工厂?)

C++ 非确定性操作的设计模式(非特定工厂?),c++,design-patterns,C++,Design Patterns,假设我有一个重复出现的代码块: Class1 c1; try { c1.parse(x); } catch(Exception& e) { Class2 c2; try { c2.parse(x); } catch(Exception& e) { Class3 c3; try { // ... } // ... } } 显然,我感兴趣的

假设我有一个重复出现的代码块:

Class1 c1;
try {
    c1.parse(x);
} catch(Exception& e) {
    Class2 c2;
    try {
        c2.parse(x);
    } catch(Exception& e) {
        Class3 c3;
        try {
            // ...
        }
        // ...
    }
}
显然,我感兴趣的是第一个
类#
(#=1,2,3,…)实例,解析不会对其抛出异常

或者,
Class1
,…,
ClassN
有一个公共超类,我可以使用它作为返回类型

考虑到此操作会在代码中重复多次,什么是抽象此操作的简明方法

可以使用STL和Boost,不可以使用C++11,因为项目要求:(
宏是灰色区域。

您可以使用类似于工厂的方法和类似于

ParserPtr CreateParser(unsinged level)
{
    switch(level)
    {
        case 0: 
            return ParserPtr(new Class0);
        //...
    }
    return nullptr;
}
然后像这样重写你的方法

void Parse()
{
    unsined errorLevel = 0;
    while(auto p = CreateParser(errorLevel))
    {
        try 
        {
            p->parse(); /*...*/
            //deallocate if ParserPtr is not shared_ptr or other smart ptr
            return;
        }
        catch(Exception & e)
        {
            ++errorLevel;
            /*Extra exception handling, deallocating p if needed*/
        }
    }
    //Handle case, when no parser succeeded
}

您可以使用类似工厂的方法和类似

ParserPtr CreateParser(unsinged level)
{
    switch(level)
    {
        case 0: 
            return ParserPtr(new Class0);
        //...
    }
    return nullptr;
}
然后像这样重写你的方法

void Parse()
{
    unsined errorLevel = 0;
    while(auto p = CreateParser(errorLevel))
    {
        try 
        {
            p->parse(); /*...*/
            //deallocate if ParserPtr is not shared_ptr or other smart ptr
            return;
        }
        catch(Exception & e)
        {
            ++errorLevel;
            /*Extra exception handling, deallocating p if needed*/
        }
    }
    //Handle case, when no parser succeeded
}

由于没有变量,并且仅限于c++03,我们不得不按照boost库的方式进行操作-前面有很多样板文件,以换取以后方便的表达式:

#include <string>
#include <stdexcept>

struct Class1 { void parse(const std::string&); };
struct Class2 { void parse(const std::string&); };
struct Class3 { void parse(const std::string&); };

struct none_type {};

template<class C>
  struct try_impl
  {
    try_impl(int index)
      : _index(index)
      {
      }
    void apply(int& which, C& c, const std::string& s) const
    {
      if (which >= 0)
        return;
      try {
        c.parse(s);
        which = _index;
      }
      catch(...) {
        // logging here?
      }
    }

    int _index;
  };

template<>
  struct try_impl<none_type>
  {
    try_impl(int index)
      : _index(index)
      {
      }
    void apply(int& which, none_type& c, const std::string& s) const
    {
    }

    int _index;
  };

// attempt to parse all given objects. Return the index of the first one that 
// passed
// return -1 if non parse correctly
//
template<class C1, class C2 = none_type, class C3 = none_type, class C4 = none_type, class C5 = none_type>
struct parse_attempt_impl
{
  static int apply(const std::string& s,C1 c1, C2 c2 = C2(), C3 c3 = C3(), C4 c4 = C4(), C5 c5 = C5())
{
  int which = -1;
  try_impl<C1>(0).apply(which, c1, s);
  try_impl<C2>(1).apply(which, c2, s);
  try_impl<C3>(2).apply(which, c3, s);
  try_impl<C4>(3).apply(which, c4, s);
  try_impl<C5>(4).apply(which, c5, s);
  return which;
}
};

// you will need to make as many of these as you need
template<class C1, class C2, class C3>
int parse_attempt(const std::string& s, C1 c1, C2 c2, C3 c3)
{
  return parse_attempt_impl<C1, C2, C3>::apply(s, c1, c2, c3);
}

template<class C1, class C2, class C3, class C4>
int parse_attempt(const std::string& s, C1 c1, C2 c2, C3 c3, C4 c4)
{
  return parse_attempt_impl<C1, C2, C3, C4>::apply(s, c1, c2, c3, c4);
}



int main(int argc, char**argv)
{
  std::string x(argv[1]);
  int which = parse_attempt(x, Class1(), Class2(), Class3());
}
#包括
#包括
结构类1{void parse(const std::string&);};
结构类2{void parse(const std::string&);};
结构类3{void parse(const std::string&);};
结构none_类型{};
模板
结构try\u impl
{
try_impl(整数索引)
:(索引)
{
}
void apply(int&which、C&C、const std::string&s)const
{
如果(哪个>=0)
返回;
试一试{
c、 解析(s);
which=_指数;
}
捕获(…){
//在这里登录?
}
}
int_指数;
};
模板
结构try\u impl
{
try_impl(整数索引)
:(索引)
{
}
void apply(int&which,none_type&c,const std::string&s)const
{
}
int_指数;
};
//尝试分析所有给定对象。返回第一个指定对象的索引
//通过
//如果未正确解析,则返回-1
//
模板
结构解析\u尝试\u执行
{
静态int应用(常量std::string&s,c1c1,c2c2=C2(),c3c3=C3(),c4c4=C4(),c5c5=C5())
{
int其中=-1;
try_impl(0).apply(哪一个,c1,s);
试着执行(1)。应用(哪一个,c2,s);
尝试应用(2),应用(哪一个,c3,s);
尝试应用(3),应用(哪一个,c4,s);
尝试实施(4)。应用(哪种,c5,s);
返回哪个;
}
};
//你将需要尽可能多的这些你需要
模板
int解析_尝试(常量std::string&s,c1c1,c2c2,c3c3)
{
返回parse_trument_impl::apply(s、c1、c2、c3);
}
模板
int解析_尝试(常量std::string&s、c1c1、c2c2、c3c3、c4c4)
{
返回parse_trument_impl::apply(s、c1、c2、c3、c4);
}
int main(int argc,字符**argv)
{
std::字符串x(argv[1]);
int=parse_尝试(x,Class1(),Class2(),Class3());
}

没有变量,并且仅限于c++03,我们被迫按照boost库的方式进行操作-前面有很多样板文件,以换取以后方便的表达:

#include <string>
#include <stdexcept>

struct Class1 { void parse(const std::string&); };
struct Class2 { void parse(const std::string&); };
struct Class3 { void parse(const std::string&); };

struct none_type {};

template<class C>
  struct try_impl
  {
    try_impl(int index)
      : _index(index)
      {
      }
    void apply(int& which, C& c, const std::string& s) const
    {
      if (which >= 0)
        return;
      try {
        c.parse(s);
        which = _index;
      }
      catch(...) {
        // logging here?
      }
    }

    int _index;
  };

template<>
  struct try_impl<none_type>
  {
    try_impl(int index)
      : _index(index)
      {
      }
    void apply(int& which, none_type& c, const std::string& s) const
    {
    }

    int _index;
  };

// attempt to parse all given objects. Return the index of the first one that 
// passed
// return -1 if non parse correctly
//
template<class C1, class C2 = none_type, class C3 = none_type, class C4 = none_type, class C5 = none_type>
struct parse_attempt_impl
{
  static int apply(const std::string& s,C1 c1, C2 c2 = C2(), C3 c3 = C3(), C4 c4 = C4(), C5 c5 = C5())
{
  int which = -1;
  try_impl<C1>(0).apply(which, c1, s);
  try_impl<C2>(1).apply(which, c2, s);
  try_impl<C3>(2).apply(which, c3, s);
  try_impl<C4>(3).apply(which, c4, s);
  try_impl<C5>(4).apply(which, c5, s);
  return which;
}
};

// you will need to make as many of these as you need
template<class C1, class C2, class C3>
int parse_attempt(const std::string& s, C1 c1, C2 c2, C3 c3)
{
  return parse_attempt_impl<C1, C2, C3>::apply(s, c1, c2, c3);
}

template<class C1, class C2, class C3, class C4>
int parse_attempt(const std::string& s, C1 c1, C2 c2, C3 c3, C4 c4)
{
  return parse_attempt_impl<C1, C2, C3, C4>::apply(s, c1, c2, c3, c4);
}



int main(int argc, char**argv)
{
  std::string x(argv[1]);
  int which = parse_attempt(x, Class1(), Class2(), Class3());
}
#包括
#包括
结构类1{void parse(const std::string&);};
结构类2{void parse(const std::string&);};
结构类3{void parse(const std::string&);};
结构none_类型{};
模板
结构try\u impl
{
try_impl(整数索引)
:(索引)
{
}
void apply(int&which、C&C、const std::string&s)const
{
如果(哪个>=0)
返回;
试一试{
c、 解析(s);
which=_指数;
}
捕获(…){
//在这里登录?
}
}
int_指数;
};
模板
结构try\u impl
{
try_impl(整数索引)
:(索引)
{
}
void apply(int&which,none_type&c,const std::string&s)const
{
}
int_指数;
};
//尝试分析所有给定对象。返回第一个指定对象的索引
//通过
//如果未正确解析,则返回-1
//
模板
结构解析\u尝试\u执行
{
静态int应用(常量std::string&s,c1c1,c2c2=C2(),c3c3=C3(),c4c4=C4(),c5c5=C5())
{
int其中=-1;
try_impl(0).apply(哪一个,c1,s);
试着执行(1)。应用(哪一个,c2,s);
尝试应用(2),应用(哪一个,c3,s);
尝试应用(3),应用(哪一个,c4,s);
尝试实施(4)。应用(哪种,c5,s);
返回哪个;
}
};
//你将需要尽可能多的这些你需要
模板
int解析_尝试(常量std::string&s,c1c1,c2c2,c3c3)
{
返回parse_trument_impl::apply(s、c1、c2、c3);
}
模板
int解析_尝试(常量std::string&s、c1c1、c2c2、c3c3、c4c4)
{
返回parse_trument_impl::apply(s、c1、c2、c3、c4);
}
int main(int argc,字符**argv)
{
std::字符串x(argv[1]);
int=parse_尝试(x,Class1(),Class2(),Class3());
}

请不要这样做。这会造成伤害。请使用返回std::optional(即在类t中:static std::optional Create(…)的“命名构造函数”,并将内部构造函数设置为私有/受保护。如果确实必须(或使用无法更改的库),请执行以下操作:

#包括
#包括
结构解析返回{};
模板
结构分析器
{
ParseReturn解析(const std::string&)
{
return ParseReturn();
}
};
模板
类解析优先
{
公众:
静态解析返回解析(const std::string&s)
{
尝试
{
返回P().parse;
}
捕获(…)
{
返回ParseFirst::parse(s);
}
}
};
模板
类解析优先

{ 公众: 静态解析返回解析(const std::string&s) { 尝试 { 返回P().parse; } 捕获(…) { //也许再扔一次? } } }; int main(){ std::字符串s; ParseFirst::解析; 返回0; }


请不要这样做。这会造成伤害。请使用返回std::optional(即在类t中:static std::optional Create(…)的“命名构造函数”,并将内部构造函数设置为私有/受保护。如果确实必须(或使用无法更改的库),请执行以下操作:

#包括
#包括
结构解析返回{};
模板
结构分析器
{
ParseReturn解析(const std::string&)
{
return ParseReturn();
}
};
模板
类解析优先
{
酒吧