成员指针类型和模板

时间:2019-12-02 12:55:59

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

首先,我要参加该考试的课程:

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<Bar, Foo> test(bar, &Bar::foo);进行实例化,除了每次写BarFoo都很无聊,因为可以推导&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<&Bar::foo> test(bar);

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

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

现在我可以将其作为模板参数而不是构造函数参数进行传递,但这一次我必须编写三个参数:test2<Bar, Foo, &Bar::foo> test2(bar);

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

3 个答案:

答案 0 :(得分: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();
    }
};

答案 1 :(得分:0)

替代方法:test t(bar, &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

答案 2 :(得分:0)

从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);
}