簡體   English   中英

如何為非成員和成員 function 指針部分專門化結構模板

[英]How to partially specialize a struct template for non-member & member function pointer

我正在做一些涉及 function 指針的模板元編程。 因為非成員和成員 function 指針的 function 類型不同,所以我試圖在兩者之間進行專門研究。 此外,我希望將指向 function 的指針作為非類型模板參數提供,而不是作為結構中 function 的參數提供。 到目前為止,這是我嘗試過的:

template <typename T, T>
struct register_method;

template <typename R, typename... Args>
struct register_method<R(Args...), R (*method)(Args...)>
{
    static R invoke(Args&&... params)
    {
        return (*method)(std::forward<Args>(params)...);
    }
};

template <typename T, typename R, typename... Args>
struct register_method<R(Args...), R (T::*method)(Args...)>
{
    static R invoke(T* instance, Args&&... params)
    {
        return (instance->*method)(std::forward<Args>(params)...);
    }
};

但是,這無法編譯(這只是第一個錯誤):

prog.cc:14:48: error: 'Args' does not refer to a value
struct register_method<R(Args...), R (*method)(Args...)>
                                               ^
prog.cc:13:35: note: declared here
template <typename R, typename... Args>
                                  ^

我不確定它想告訴我什么。 我的目標是像這樣使用這些對象:

void the_func(float val)
{
    std::cout << "the_func called: " << val << "\n";
}

int main()
{
    register_method<decltype(&the_func), &the_func>::invoke(50.f);
}

我怎樣才能得到這個工作? 如果有機會簡化,那也太好了(例如,如果我可以將 function 指針傳遞給模板而不是同時執行decltype ,這應該會減少樣板。

編輯:還想補充一點,我需要對非成員函數和成員函數進行單獨專門化的原因不僅僅是 function 類型不同。 由於我附加到不同 function 類型的業務規則,兩者之間存在不同的 static state。 我在這里省略了這些細節以保持問題簡單。

以下是修復代碼的方法:

template <typename T, T>
struct register_method;

template <typename R, typename... Args, R (*method)(Args...)>
struct register_method<R (*)(Args...), method>
{
    template <typename ...P>
    static R invoke(P &&... params)
    {
        return (*method)(std::forward<P>(params)...);
    }
};

template <typename T, typename R, typename... Args, R (T::*method)(Args...)>
struct register_method<R (T::*)(Args...), method>
{
    template <typename ...P>
    static R invoke(T *instance, P &&... params)
    {
        return (instance->*method)(std::forward<P>(params)...);
    }
};

請注意,您必須引入一個單獨的參數包才能使轉發引用起作用,因為它們僅在推導模板參數時才起作用。


這是使用 C++17 auto模板參數的替代解決方案:

template <auto method>
struct register_method;

template <typename R, typename... Args, R (*method)(Args...)>
struct register_method<method>
{
    template <typename ...P>
    static R invoke(P &&... params)
    {
        return (*method)(std::forward<P>(params)...);
    }
};

template <typename T, typename R, typename... Args, R (T::*method)(Args...)>
struct register_method<method>
{
    template <typename ...P>
    static R invoke(T *instance, P &&... params)
    {
        return (instance->*method)(std::forward<P>(params)...);
    }
};

專業化應該看起來像

template <typename T, T>
struct register_method;

template <typename R, typename... Args, R (*method)(Args...)>
struct register_method<R (*)(Args...), method>
{
    static R invoke(Args... params)
    {
        return (*method)(std::forward<Args>(params)...);
    }
};

template <typename C, typename R, typename... Args, C (T::*method)(Args...)>
struct register_method<R (C::*)(Args...), method>
{
    static R invoke(T* instance, Args... params)
    {
        return (instance->*method)(std::forward<Args>(params)...);
    }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM