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專門化。

原作者:
...