【问题标题】:pointer-to-member type and template指向成员类型和模板的指针
【发布时间】:2019-12-02 12:55:59
【问题描述】:

首先我要为这个测试上课:

struct Foo {
  void test() {
    std::cout << "test" << std::endl;
  }
};

struct Bar {
  Foo foo;
};

和一个模板类,它在构造时接受指向成员的指针:

template<typename Type, typename MemberType>
class test {
 public:
  test(Type &t, MemberType Type::* p) : t(t) {
    (t.*p).test();
  }
  Type &t;
};

效果很好,可以使用test&lt;Bar, Foo&gt; test(bar, &amp;Bar::foo);进行实例化,只是每次都写Bar和Foo很无聊,因为可以推导出&amp;Bar::foo,所以我决定做一个专门化版本:

template<typename Type, typename MemberType, MemberType Type::*p>
class test<MemberType Type::*p> {
 public:
  test(Type &t) {
    (t.*p).test();
  }
};

好的,我真的不知道该怎么做,我只想传递一个 MemberType Type::*p 作为唯一的模板参数,如下所示:test&lt;&amp;Bar::foo&gt; test(bar);

然后我创建一个全新的类:

template<typename Type, typename MemberType, MemberType Type::*p>
class test2 {
 public:
  test2(Type &t) {
    (t.*p).test();
  }
};

现在我可以作为模板参数而不是构造函数参数传递,但是这次我必须写三个参数:test2&lt;Bar, Foo, &amp;Bar::foo&gt; test2(bar);

那么我可以简单地使用test&lt;&amp;Bar::foo&gt; test(bar); 的正确方法是什么?

【问题讨论】:

    标签: c++ templates pointer-to-member


    【解决方案1】:

    你几乎猜对了。

    主模板必须使用auto 模板参数(C++17 特性):

    template <auto MemberPtr> class test {};
    

    然后是专业化:

    template <typename Type, typename MemberType, MemberType Type::*p>
    class test<p> // Note `p` instead of `MemberType Type::*p`.
    {
      public:
        test(Type &t)
        {
            (t.*p).test();
        }
    };
    

    【讨论】:

      【解决方案2】:

      另一种选择:test t(bar, &amp;Bar::foo);

      这使用您的主模板:

      template<typename Type, typename MemberType>
      class test {
       public:
        test(Type &t, MemberType Type::* p) : t(t) {
          (t.*p).test();
        }
        Type &t;
      };
      

      和template argument deduction (TAD)。

      现场演示:https://coliru.stacked-crooked.com/a/52ee3ddba011473b

      【讨论】:

        【解决方案3】:

        从 C++17 开始,这是用户定义的演绎指南的确切预期用例。 C++17 之前的一个经常使用的 make 函数。

        #include <iostream>
        
        template<typename Type, typename MemberType>
        class test {
         public:
          test(Type &t, MemberType Type::* p) : t(t) {
            (t.*p).test();
          }
          Type &t;
        };
        
        // C++17 user defined deduction guide
        template<typename Type, typename MemberType>
        test(Type &t, MemberType Type::* p) -> test<std::decay_t<decltype(t)>, decltype(static_cast<std::decay<decltype(t)>>(t).*p) >;
        
        // pre C++17 make function
        template<typename Type, typename MemberType>
        test<Type, MemberType> make_test(Type &t, MemberType Type::* p) {
            return test<Type, MemberType>(t, p);
        }
        
        
        struct Foo {
          void test() {
            std::cout << "test" << std::endl;
          }
        };
        
        struct Bar {
          Foo foo;
        };
        
        
        int main() {
            Bar b;
            test<Bar, Foo> t1 (b, &Bar::foo);
            // Only works in C++17
            test t2(b, &Bar::foo);
            auto t3 = make_test(b, &Bar::foo);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-04
          • 2012-07-05
          • 2013-02-15
          • 2010-09-13
          • 2018-03-24
          相关资源
          最近更新 更多