[英]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.