簡體   English   中英

為什么這個函數模板調用工作?

[英]Why does this function template call work?

以下代碼編譯:

template<int...>
struct Indices {};

template<int J, int ...I>
void foo(Indices<I...>) {}

int main(int argc, char **argv)
{
  foo<2>(Indices<3,4,5>()); //why does this work?
  return 0;
}

在函數調用中,在我看來, J參數變為2...I參數變為3,4,5

但為什么這有效呢? 我只在foo<2>指定了2 ,這意味着我將J指定為2並且...I沒有任何指示。 為什么我仍然可以指定...I通過Indices參數? 這里使用了什么模板機制?

更新:當前的答案並沒有解釋為什么我可以有一個參數沒有推斷(明確指定)但其他參數推斷。 什么時候這確實有效? 我希望我不依賴於未定義的行為。 標准是否允許我正在做的事情?

參數unpack ...I是由編譯器從函數參數中推導出來的。 它被稱為模板參數推導

以下是一些簡單但有用的示例:

template<typename T> 
void f(T const&) {}

f(10);   //T is deduced as int
f(10.0); //T is deduced as double
f("10"); //T is deduced as char[3]

標准庫中的許多函數都是函數模板,通常會推導出模板參數。 這是一個例子:

std::vector<int> vi;
std::vector<std::string> vs;
//...
std::sort(vi.begin(), vi.end()); //template argument deduction
std::sort(vs.begin(), vs.end()); //template argument deduction

這里std::sort是一個函數模板,但正如您所看到的,我們沒有顯式傳遞模板參數。 這是因為模板參數是由編譯器本身從函數參數推導出來的。

希望有所幫助。

要添加到nawaz答案:必須提供無法推斷的模板參數,並且提供的模板參數必須按照定義的順序排列。 這意味着如果模板參數可能需要提供,最好將其放在模板參數列表中的第一位。 例如

template<typename A, typename B> A foo(B);
template<typename B, typename A> A bar(B);

auto x = foo<int>(0.0);       // A=int, B=double;
auto y = foo<int,double>(0);  // A=int, B=double, argument implicitly cast to double
auto z = bar<int>(0);         // error: cannot deduce A
auto w = bar<int,double>(0);  // A=double, B=int;

在這兩種情況下,可以推導出B (從函數參數類型),但A不能。 所以foo更方便,因為只能提供一個模板參數。 使用bar ,第一個模板參數是可推導的,但不是第二個。 因此,必須提供兩者。 (只是為了澄清changning auto to doubleint與手頭的問題無關。)

如果可以在編譯時推斷出其他參數,則允許僅為函數調用指定部分參數(第一個)。 例:

template<typename Ret, typename Arg>
Ret cast(Arg x){
    return x;
}

cast<double>(5);

實際上你甚至可以編譯這段代碼:

template<int...>
struct Indices {};

template<int J, int ...I>
void foo(Indices<I...>) {}

int main(int argc, char **argv)
{
  foo<2,3>(Indices<3,4,5>()); //ok 2,3,4,5 starts with 2,3
  return 0;
}

但不是這個:

template<int...>
struct Indices {};

template<int J, int ...I>
void foo(Indices<I...>) {}

int main(int argc, char **argv)
{
  foo<2,1>(Indices<3,4,5>()); //no way to make x,3,4,5 start with 2,1
  return 0;
}

參見C ++ 11標准(N3242草案)的第14.1.8部分第3節。

可以推導出(14.8.2)或從默認模板參數獲得的尾隨模板參數可以從顯式模板參數列表中省略 未以其他方式推導出的尾隨模板參數包(14.5.3)將被推導為空的模板參數序列。 如果可以推導出所有模板參數,則可以省略它們; 在這種情況下,也可以省略空模板參數列表<>本身。 在完成演繹和失敗的上下文中,或者在沒有進行演繹的上下文中,如果指定了模板參數列表,並且它與任何默認模板參數一起識別單個函數模板特化,那么template-id是左值用於功能模板專業化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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