代码之家  ›  专栏  ›  技术社区  ›  Jonathan Mee

我可以获得成员函数模板参数的拥有对象吗?

  •  10
  • Jonathan Mee  · 技术社区  · 6 年前

    给定对象:

    struct foo {
        void func();
    };
    

    现在给出模板化函数声明:

    template<typename T, T F>
    void bar();
    

    所以呢 bar 将接受这样的成员函数:

    bar<decltype(&foo::func), &foo::func>()
    

    在…的身体里 酒吧 我要恢复类型 foo T . 我能做到吗?我希望能够做到这样:

    get_obj<T> myfoo;
    
    (myfoo.*F)();
    

    get_obj

    2 回复  |  直到 6 年前
        1
  •  13
  •   Yakk - Adam Nevraumont    6 年前
    template<class T>
    struct get_memfun_class;
    template<class R, class T, class...Args>
    struct get_memfun_class<R(T::*)(Args...)> {
      using type=T;
    };
    template<class T>
    using get_memfun_class_t=typename get_memfun_class<T>::type;
    
    
    template<auto M>
    using class_of_memfun = get_memfun_class_t< decltype(M) >;
    

    class_of_memfun<F> 然后是memberfunction的类 F

    要处理const/volatile/etc,您必须完成一系列的版本。这真烦人。下面是一个例子:

    template<class T>
    struct get_memfun_class;
    #define GET_MEMFUN_CLASS(...) \
    template<class R, class T, class...Args> \
    struct get_memfun_class<R(T::*)(Args...) __VA_ARGS__> { \
      using type=T; \
    }
    

    template<class R, class T, class...Args> \
    struct get_memfun_class<R(T::*)(Args...) __VA_ARGS__> { \
      using type=T __VA_ARGS__; \
    }
    

    选择后,需要编写上述宏的24种用法:

    GET_MEMFUN_CLASS();
    GET_MEMFUN_CLASS(const);
    GET_MEMFUN_CLASS(volatile);
    GET_MEMFUN_CLASS(const volatile);
    GET_MEMFUN_CLASS(&);
    GET_MEMFUN_CLASS(const&);
    GET_MEMFUN_CLASS(volatile&);
    GET_MEMFUN_CLASS(const volatile&);
    GET_MEMFUN_CLASS(&&);
    GET_MEMFUN_CLASS(const&&);
    GET_MEMFUN_CLASS(volatile&&);
    GET_MEMFUN_CLASS(const volatile&&);
    GET_MEMFUN_CLASS(noexcept);
    GET_MEMFUN_CLASS(const noexcept);
    GET_MEMFUN_CLASS(volatile noexcept);
    GET_MEMFUN_CLASS(const volatile noexcept);
    GET_MEMFUN_CLASS(& noexcept);
    GET_MEMFUN_CLASS(const& noexcept);
    GET_MEMFUN_CLASS(volatile& noexcept);
    GET_MEMFUN_CLASS(const volatile& noexcept);
    GET_MEMFUN_CLASS(&& noexcept);
    GET_MEMFUN_CLASS(const&& noexcept);
    GET_MEMFUN_CLASS(volatile&& noexcept);
    GET_MEMFUN_CLASS(const volatile&& noexcept);
    #undef GET_MEMFUN_CLASS
    
    template<class T>
    using get_memfun_class_t=typename get_memfun_class<T>::type;
    

    我不知道有什么方法可以避免做所有这些24个专业的全覆盖。如果你认为这是愚蠢的,你是对的,请通过向C++标准委员会提出一个修正来表达你的烦恼。

    如果你为不止一个特征做这样的事情,你可以在一个地方写下“剥离左值、右值、无例外和cv限定符”,然后把它们一块一块地传递下去。

    Live example .

        2
  •  7
  •   463035818_is_not_an_ai    6 年前

    如果你限制 void(T::mem_fun)() :

    #include <iostream>
    struct foo {
        void func(){ std::cout << "foo"; }
    };
    
    template <typename T> struct get_type;
    template <typename T> struct get_type<void(T::*)()> {
        using type = T;
    };
    template <typename T> using get_type_t = typename get_type<T>::type;
    
    
    template<typename T, T F> void bar(){
        get_type_t<T> myfoo;
        (myfoo.*F)();
    }
    
    int main () {
        bar<decltype(&foo::func), &foo::func>();
    }