簡體   English   中英

如何在c ++的列表末尾推導出模板參數?

[英]How can I deduce template parameters at the end of the list in c++?

我正在嘗試編寫一個模仿三個方面的函數:

  1. 第一種。
  2. 第二種。
  3. 帶參數的函數First和Second類型。

代碼如下所示:

#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 我想在barbar 參數應該只是(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.

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