我正在嘗試創建一個類模板,它需要一個型別和一個函式指標作為模板引數。函式指標應該是傳入型別的成員函式。我希望類模板的用戶能夠傳入傳入型別的 void 成員函式。然后將在以下實體上呼叫該成員函式每次呼叫類模板的某個函式時傳入的型別。這有點難以解釋,但它應該像這樣作業:
template<Type, Function> // For the purpose of explaining it
class Foo
{
public:
template<Args... args>
void callOnAll(Args... args)
{
for(Type* ptr : ptrs_)
{
ptr->Function(std::forward<Args>(args)...);
}
}
private:
std::vector<Type*> ptrs_;
}
假設這樣的事情是可能的(我意識到它可能不是),關鍵必須是正確獲取類的模板引數,并正確獲取update函式。這是我想出的,但我仍然無法讓它作業:
template<typename T, template<typename... Args> void(T::*func)(Args... args)>
class EngineSystem
{
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
((*handler).*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
上面的代碼不能編譯。它指向我宣告類的模板引數的行,下劃線void并說expected 'class' or 'typename'.
是否清楚我想要實作的目標,有可能嗎?
uj5u.com熱心網友回復:
C 不允許非型別模板模板引數。這意味著您不能為您的成員函式指標引數設定引數包。
假設您使用的是 C 17 或更高版本,則可以改用auto模板引數:
template<typename T, auto func>
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
現場演示
從技術上講,它將接受任何物件 for func,但假設update被呼叫,那么(handler->*func)(std::forward<Args>(args)...)仍然必須格式正確,否則編譯將失敗。
如果您希望編譯即使update從未被呼叫也失敗,您可以使用一些型別特征和 a static_assert(或一些 SFINAE 黑客,如果您需要它)來確保它func實際上是一個指向以下成員函式的指標T:
template <typename T, typename U>
struct IsPointerToMemberOf : std::false_type {};
template <typename T, typename U>
struct IsPointerToMemberOf<T, U T::*> : std::true_type {};
template <typename T, typename U>
struct IsPointerToMemberFunctionOf
: std::integral_constant<
bool,
IsPointerToMemberOf<T, U>::value && std::is_member_function_pointer<U>::value
>
{};
template<typename T, auto func>
class EngineSystem
{
static_assert(IsPointerToMemberFunctionOf<T, decltype(func)>::value, "func must be a pointer to a member function of T");
//...
};
現場演示
uj5u.com熱心網友回復:
#include <iostream>
#include <vector>
template <typename T, typename... Args>
class EngineSystem
{
public:
EngineSystem(void(T::*fun)(Args... args)): fun(fun)
{
}
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*fun)(std::forward<Args>(args)...);
}
}
void push(T* t){
handlers_.push_back(t);
}
private:
void(T::*fun)(Args... args);
std::vector<T*> handlers_;
};
struct A {
int x = 3;
void fn(int a, int b){
std::cout << a << b << x;
}
};
template <typename T, typename... Args>
auto makeEngine(void(T::*fun)(Args... args)){
return EngineSystem<T, Args...>(fun);
}
int main() {
EngineSystem<A, int, int> as(&A::fn);
// or deduce types automatically
auto es = makeEngine(&A::fn);
A a;
es.push(&a);
es.update(1,2);
return 0;
}
https://gcc.godbolt.org/z/Pcdf9K9nz
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/338550.html
上一篇:如何檢索函式輸出的最大值
