你無法定義僅有一個模板類模板參數並接受一個函數指針,其參數必須被推導出來。
要做到這一點,你必須使用這樣的事情:
template<typename F, F *func>
struct S;
template<typename R, typename... A, R(*f)(A...)>
struct S<R(A...), f> {};
和一個漂亮的醜陋符號像這樣的:
S<decltype(f), &f> s;
可能的替代方法是使用函數指針作爲參數傳遞給構造函數:
#include<type_traits>
#include<utility>
template<typename>
struct S;
template<typename R, typename... A>
struct S<R(A...)> {
S(R(*f)(A...)): f{f} {}
R operator()(A... args) { return f(args...); }
private:
R(*f)(A...);
};
void g() {}
int h(int) { return 0; }
int main() {
S<void(void)> s1{&g};
S<int(int)> s2{&h};
s1();
s2(42);
}
如果你想要去一點,並有一個更靈活的解決方案,你可以解決它也可以通過使用lambda表達式和工廠方法:
#include<type_traits>
#include<utility>
template<typename F>
struct S: F { S(F &&f): F{std::forward<F>(f)} {} };
template<typename F>
constexpr auto create(F &&f)
-> decltype(S<typename std::decay<F>::type>{std::forward<F>(f)}) {
return S<typename std::decay<F>::type>{std::forward<F>(f)};
}
void g() {}
int h(int) { return 0; }
int main() {
auto s1 = create([](){ g(); });
auto s2 = create([](int i){ return h(i); });
s1();
s2(42);
}
作爲一個側面說明,如果你能使用C++ 14,最後一個片斷的語法變得更漂亮:
#include<type_traits>
#include<utility>
template<typename F>
struct S: F { S(F &&f): F{std::forward<F>(f)} {} };
template<typename F>
constexpr auto create(F &&f) {
return S<std::decay_t<F>>{std::forward<F>(f)};
}
void g() {}
int h(int) { return 0; }
int main() {
auto s1 = create([](){ g(); });
auto s2 = create([](auto&&... args){ return h(std::forward<decltype(args)>(args)...); });
s1();
s2(42);
}
就個人而言,我也將有條件地提供一個助手宏(只有在包含頭文件之前定義了一些其他宏,例如'ENABLE_MAKE_FOO'時才定義),類似於'#define make_foo(func_)foo',可用作'make_foo(func0)f0;'或'auto f0 = make_foo(func0){};' –