c++17 - C++17 - 将泛型成员函数定义为模板参数,而不使用冗余成员签名作为参数

67 3

我尝试编写一个通用成员委托函数(基于这个很酷的答案泛型成员函数指针作为模板参数 ):


template <typename T, T>


class Delegate {};



template <typename T, typename R, typename... Args, R (T::*TMember)(Args...)>


class Delegate<R (T::*)(Args...), TMember> {


 public:


 Delegate(T &obj) : obj_{obj} {}



 R operator()(Args &&... args) const noexcept(


 noexcept((obj_.*TMember)(std::forward<Args>(args)...))) {


 return (obj_.*TMember)(std::forward<Args>(args)...);


 }



 private:


 T &obj_;


};



template <typename T, typename R, typename... Args, R (T::*TMember)(Args...) const>


class Delegate<R (T::*)(Args...) const, TMember> {


 public:


 Delegate(const T &obj) : obj_{obj} {}



 R operator()(Args &&... args) const noexcept(


 noexcept((obj_.*TMember)(std::forward<Args>(args)...))) {


 return (obj_.*TMember)(std::forward<Args>(args)...);


 }



 private:


 const T &obj_;


};



struct Foo {


 int Bar(int a, int b) noexcept { return a + b; }



 int ConstBar(int a, int b) const noexcept { return a + b; }


};



int main() {


 Foo obj;


 auto add = Delegate<int (Foo::*)(int, int), &Foo::Bar>(obj);



 std::cout << add(1, 2) << std::endl; // 3



 const Foo const_obj;


 auto const_add =


 Delegate<int (Foo::*)(int, int) const, &Foo::ConstBar>(const_obj);



 std::cout << const_add(3, 4) << std::endl; // 7



 return 0;


}



问题是:

  • 我是否可以在Delegate实例化中将模糊指针忽略为成员,如下所示: Delegate<Foo::Bar>(obj)
  • 我很懒,而且指定成员签名对我来说太难了,是否可以基于单模板参数推导出模板签名? Delegate<int (Foo::*)(int, int), &Foo::Bar>(obj)变成Delegate<&Foo::Bar>(obj)
  • 要编写通用代码,需要将noexcept说明符从成员传播到委托的operator()noexcept(noexcept((obj_.*TMember)(std::forward<Args>(args)...)))可以从return主体本身派生noexcept说明符,而不是同时指定正文?
  • 我需要对两个版本进行专门化- const和non- const ,编译器可以为我做这个? 如果volatile /const volatile专门化如何,我应该重复去复制相同的代码?

时间: 原作者:

118 1
  • 可以在委托实例化中将模糊指针忽略为成员,如下所示: Delegate(obj)?

根据这个答案,我想答案是"不行"

  • 我很懒,而且指定成员签名对我来说太难了,我们是否可以基于单个模板参数推断模板签名,从而使 Delegate(obj) 变为Delegate <

你标记了C 17,是的,你可以使用auto


template <auto>


class Delegate


 { };



template <typename T, typename R, typename... Args,


 R (T::*TMember)(Args...)>


class Delegate<TMember>



// ...



template <typename T, typename R, typename... Args,


 R (T::*TMember)(Args...) const>


class Delegate<TMember>



// ...



 // ... 



 auto add = Delegate<&Foo::Bar>(obj);



 // ...



 auto const_add =


 Delegate<&Foo::ConstBar>(const_obj);



  • 我需要专门化两个版本-const和non-const ,编译器可以为我做这个?

如果你为Delegate创建了一个基类,如下所示,


template <auto TMember, typename T, typename R, typename ... Args>


class DelegateBase


 {


 public:


 DelegateBase (T & obj) : obj_{obj}


 { }



 R operator() (Args &&... args) const


 noexcept


 (noexcept((std::declval<T>().*TMember)(std::forward<Args>(args)...)))


 { return (obj_.*TMember)(std::forward<Args>(args)...); }



 private:


 T & obj_;


 };



你可以使用DelegateBase编写Delegate


template <auto>


class Delegate


 { };



template <typename T, typename R, typename... Args,


 R (T::*TMember)(Args...)>


class Delegate<TMember>


 : public DelegateBase<TMember, T, R, Args...>


 { using DelegateBase<TMember, T, R, Args...>::DelegateBase; };



template <typename T, typename R, typename... Args,


 R (T::*TMember)(Args...) const>


class Delegate<TMember>


 : public DelegateBase<TMember, T const, R, Args...>


 { using DelegateBase<TMember, T const, R, Args...>::DelegateBase; };



我想你可以添加几个volatile /const volatile专门化。

原作者:
...