<small id='R7si9'></small><noframes id='R7si9'>

    <legend id='R7si9'><style id='R7si9'><dir id='R7si9'><q id='R7si9'></q></dir></style></legend>
        <bdo id='R7si9'></bdo><ul id='R7si9'></ul>

        <tfoot id='R7si9'></tfoot>
      1. <i id='R7si9'><tr id='R7si9'><dt id='R7si9'><q id='R7si9'><span id='R7si9'><b id='R7si9'><form id='R7si9'><ins id='R7si9'></ins><ul id='R7si9'></ul><sub id='R7si9'></sub></form><legend id='R7si9'></legend><bdo id='R7si9'><pre id='R7si9'><center id='R7si9'></center></pre></bdo></b><th id='R7si9'></th></span></q></dt></tr></i><div id='R7si9'><tfoot id='R7si9'></tfoot><dl id='R7si9'><fieldset id='R7si9'></fieldset></dl></div>

        “类型开关"在 C++11 中构造

        quot;type-switchquot; construct in C++11(“类型开关在 C++11 中构造)

        <small id='LrxaG'></small><noframes id='LrxaG'>

              <tbody id='LrxaG'></tbody>

            <legend id='LrxaG'><style id='LrxaG'><dir id='LrxaG'><q id='LrxaG'></q></dir></style></legend>
            • <bdo id='LrxaG'></bdo><ul id='LrxaG'></ul>
            • <tfoot id='LrxaG'></tfoot>

              1. <i id='LrxaG'><tr id='LrxaG'><dt id='LrxaG'><q id='LrxaG'><span id='LrxaG'><b id='LrxaG'><form id='LrxaG'><ins id='LrxaG'></ins><ul id='LrxaG'></ul><sub id='LrxaG'></sub></form><legend id='LrxaG'></legend><bdo id='LrxaG'><pre id='LrxaG'><center id='LrxaG'></center></pre></bdo></b><th id='LrxaG'></th></span></q></dt></tr></i><div id='LrxaG'><tfoot id='LrxaG'></tfoot><dl id='LrxaG'><fieldset id='LrxaG'></fieldset></dl></div>

                  本文介绍了“类型开关"在 C++11 中构造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  一直以来,我发现自己在做这样的事情:

                  All the time, I find myself doing something like this:

                  Animal *animal = ...
                  if (Cat *cat = dynamic_cast<Cat *>(animal)) {
                      ...
                  }
                  else if (Dog *dog = dynamic_cast<Dog *>(animal)) {
                      ...
                  }
                  else { assert(false); }
                  

                  当我看到 C++11 中的闭包时,我想知道这样的事情可能吗?

                  Once I see closures in C++11, I wonder, is something like this possible?

                  Animal *animal = ...
                  typecase(animal,
                      [](Cat *cat) {
                          ...
                      },
                      [](Dog *dog) {
                          ...
                      });
                  

                  实现 typecase 应该很容易,但我一直遇到一个问题,它无法找出函数的参数,所以它不知道尝试 dynamic_cast 到什么,因为很难推断 lambdas 的参数.用了几天的时间在 google 和 SO 上搜索,但终于弄明白了,所以我将在下面分享我的答案.

                  Implementing typecase should have been easy, but I keep running into a problem where it can't figure out the function's argument, so it can't know what to try to dynamic_cast to, because it's hard to deduce lambdas' parameters. Took a few days of searching google and SO, but finally figured it out, so I'll share my answer below.

                  推荐答案

                  感谢 ecatmur 在 https://stackoverflow.com/上的回答a/13359520 我能够从 lambda 中提取签名.完整的解决方案如下所示:

                  Thanks to an answer from ecatmur at https://stackoverflow.com/a/13359520 I was able to extract the signature from the lambda. The full solution looks like this:

                  // Begin ecatmur's code
                  template<typename T> struct remove_class { };
                  template<typename C, typename R, typename... A>
                  struct remove_class<R(C::*)(A...)> { using type = R(A...); };
                  template<typename C, typename R, typename... A>
                  struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
                  template<typename C, typename R, typename... A>
                  struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
                  template<typename C, typename R, typename... A>
                  struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
                  
                  template<typename T>
                  struct get_signature_impl { using type = typename remove_class<
                      decltype(&std::remove_reference<T>::type::operator())>::type; };
                  template<typename R, typename... A>
                  struct get_signature_impl<R(A...)> { using type = R(A...); };
                  template<typename R, typename... A>
                  struct get_signature_impl<R(&)(A...)> { using type = R(A...); };
                  template<typename R, typename... A>
                  struct get_signature_impl<R(*)(A...)> { using type = R(A...); };
                  template<typename T> using get_signature = typename get_signature_impl<T>::type;
                  // End ecatmur's code
                  
                  // Begin typecase code
                  template<typename Base, typename FirstSubclass, typename... RestOfSubclasses>
                  void typecase(
                          Base *base,
                          FirstSubclass &&first,
                          RestOfSubclasses &&... rest) {
                  
                      using Signature = get_signature<FirstSubclass>;
                      using Function = std::function<Signature>;
                  
                      if (typecaseHelper(base, (Function)first)) {
                          return;
                      }
                      else {
                          typecase(base, rest...);
                      }
                  }
                  template<typename Base>
                  void typecase(Base *) {
                      assert(false);
                  }
                  template<typename Base, typename T>
                  bool typecaseHelper(Base *base, std::function<void(T *)> func) {
                      if (T *first = dynamic_cast<T *>(base)) {
                          func(first);
                          return true;
                      }
                      else {
                          return false;
                      }
                  }
                  // End typecase code
                  

                  示例用法如下:

                  class MyBaseClass {
                  public:
                      virtual ~MyBaseClass() { }
                  };
                  class MyDerivedA : public MyBaseClass { };
                  class MyDerivedB : public MyBaseClass { };
                  
                  
                  int main() {
                      MyBaseClass *basePtr = new MyDerivedB();
                  
                      typecase(basePtr,
                          [](MyDerivedA *a) {
                              std::cout << "is type A!" << std::endl;
                          },
                          [](MyDerivedB *b) {
                              std::cout << "is type B!" << std::endl;
                          });
                  
                      return 0;
                  }
                  

                  如果有人有任何改进,请告诉我!

                  If anyone has any improvements, please tell me!

                  这篇关于“类型开关"在 C++11 中构造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  Is Type(::x); valid?(是类型(::x);有效的?)
                  Difference between an inline function and static inline function(内联函数和静态内联函数的区别)
                  Compilation fails randomly: quot;cannot open program databasequot;(编译随机失败:“无法打开程序数据库)
                  Too many initializers error for a simple array in bcc32(bcc32 中的简单数组的初始值设定项过多错误)
                  No Member named stoi in namespace std(命名空间 std 中没有名为 stoi 的成员)
                  Error using a constexpr as a template parameter within the same class(在同一个类中使用 constexpr 作为模板参数时出错)

                      <legend id='lBJW1'><style id='lBJW1'><dir id='lBJW1'><q id='lBJW1'></q></dir></style></legend>

                          <tfoot id='lBJW1'></tfoot>
                        1. <small id='lBJW1'></small><noframes id='lBJW1'>

                        2. <i id='lBJW1'><tr id='lBJW1'><dt id='lBJW1'><q id='lBJW1'><span id='lBJW1'><b id='lBJW1'><form id='lBJW1'><ins id='lBJW1'></ins><ul id='lBJW1'></ul><sub id='lBJW1'></sub></form><legend id='lBJW1'></legend><bdo id='lBJW1'><pre id='lBJW1'><center id='lBJW1'></center></pre></bdo></b><th id='lBJW1'></th></span></q></dt></tr></i><div id='lBJW1'><tfoot id='lBJW1'></tfoot><dl id='lBJW1'><fieldset id='lBJW1'></fieldset></dl></div>
                            <bdo id='lBJW1'></bdo><ul id='lBJW1'></ul>
                              <tbody id='lBJW1'></tbody>