![](/img/trans.png)
[英]how to use a sublass of a template class to deduce the template parameters of a template function in C++?
[英]How can I deduce template parameters at the end of the list in c++?
我正在嘗試編寫一個模仿三個方面的函數:
代碼如下所示:
#include <iostream>
#include <typeinfo>
using namespace std;
// Assume that this function is in a library. Can't be modified.
void bar(int x, int y) {
cout << x << endl;
cout << y << endl;
}
// My code is below:
template <typename Type1, typename Type2, void (*fn)(Type1, Type2)>
void foo(Type1 x1, Type2 x2) {
fn(x1,x2);
}
int main() {
foo<int, int, &bar>(1,2);
}
代碼可以工作,但我不滿意我的模板必須包含<int, int, &bar>
。 我希望編譯器會發現bar有int, int
作為參數並計算出來。
我嘗試首先列出函數,然后在類型聲明中,但在聲明中, Type1
在函數原型中未被識別,因為它稍后在同一原型中定義。
有優雅的解決方案嗎?
編輯:我絕對不想將指針傳遞給堆棧上的bar
。 我想在bar
上bar
。 參數應該只是(1, 2)
。
Edit2:就此而言,我的意思是我想寫foo<&bar>(1,2)
。
這是我沒有將函數作為參數傳遞的解決方案:
void bar(int a, int b) {
cout << a << " " << b << endl;
}
template <class F, F *fn>
struct Foo {
template <class... Args>
static decltype(auto) foo(Args &&... args) {
return fn(std::forward<Args>(args)...);
}
};
int main() {
Foo<decltype(bar), bar>::foo(1, 2);
return 0;
}
你可以看到你必須寫兩次bar
,一次是它的類型,一次是它的價值,但我認為這是一個小小的不便。
或簡單版本(如果你不能使用c ++ 11)
template <class F, F* fn>
struct Foo {
template <class T1, class T2>
static void foo(T1 t1, T2 t2) {
fn(t1, t2);
}
};
對於那些不介意將函數obj作為參數傳遞的人:
選項1:
template <class T1, class T2>
void foo(T1 x1, T2 x2, void (*fn)(T1, T2)) {
fn(x1, x2);
}
foo(1, 2, bar);
選項2:
template <class T1, class T2, class F = void(*)(T1, T2)>
void foo(T1 x1, T2 x2, F fn)) {
fn(x1, x2);
}
foo(1, 2, bar);
選項3:
template <class T1, class T2, class F>
void foo(T1 x1, T2 x2, F fn)) {
fn(x1, x2);
}
foo(1, 2, bar);
選項3b(真實交易):
template <class T1, class T2, class F>
void foo(T1 &&x1, T2 &&x2, F &&fn)) {
std::forward<F>(fn)(std::forward(x1), std::forward(x2));
}
foo(1, 2, bar);
選項4(真正的實際交易)(好......取決於你需要的)
template <class F, class... Args>
decltype(auto) foo(F &&fn, Args &&... args) {
return std::forward<F>(fn)(std::forward<Args>(args)...);
}
您甚至可以避免使用包含該值的臨時struct
來鍵入bar
兩次。 任何體面的編譯器都會對結構進行優化,盡管作為foo
的參數傳遞,但不會在堆棧上傳遞該bar
:
template <typename Fn>
struct FooT {
Fn &fn;
FooT(Fn fn):fn(fn){}
operator Fn *() {return fn;}
};
template <typename Fn>
inline FooT<Fn> foo(Fn *fn) {return FooT<Fn>(fn);}
int main() {
foo(bar)(1,2);
}
注意:轉換為Fn *
允許直接調用fn
,無需任何參數轉發。 如果需要,也可以使用模板operator ()
傳遞/轉發參數來調用它,但這似乎更簡單並且有效。 如果您需要在調用fn
之前或之后執行更多操作,模板化實現可能會很方便。 我不是前瞻性的論點,只是傳遞它們,為了保持簡單,如果有必要,這可以很容易地改變:
template <typename Fn>
struct FooT {
Fn &fn;
FooT(Fn fn):fn(fn){}
template <typename Type1, typename Type2>
void operator ()(Type1 x1, Type2 x2) {
fn(x1,x2);
}
};
Visual Studio 2012生成的代碼,禁用整個程序優化,僅擴展內聯(/ Ob1):
foo(bar)(1,2);
011E16F0 push 2
011E16F2 push 1
011E16F4 call bar (011E13D0h)
011E16F9 add esp,8
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.