簡體   English   中英

這部分功能模板是否專業化?

[英]Is this partial function template specialization?

回答完這個問題后,我想到了這個

我有一個簡單的函數模板(C ++ 11):

template<class elem_t, class list_t>
bool in_list(const elem_t& elem, const list_t& list) {
   for (const auto& i : list) {
      if (elem == i) {
         return true;
      }
   }
   return false;
}

但是GCC發出了警告,因為它似乎不喜歡將模板參數推斷為std :: initializer_list。 所以,不假思索地,我做了一個專業化:

template<class elem_t>
bool in_list(const elem_t& elem, std::initializer_list<elem_t> list) {
   for (const auto& i : list) {
      if (elem == i) {
         return true;
      }
   }
   return false;
}

這很有效。 沒有更多的警告。 但當我再看一遍並考慮它時,我記得C ++不支持對函數模板進行部分模板特化。 但這就是看起來的樣子。 我唯一的猜測是這是允許的,因為std :: initializer_list仍然依賴於模板參數,所以它本質上是一個不同的模板。 但我不確定這是不是應該是這樣(是不是有一些模板沒有重載?)。

接受這個是標准行為嗎? 為什么?

作為一個額外的問題,為什么GCC不喜歡將模板參數推斷為std :: initializer_list? 期望我復制並粘貼代碼並用std :: initializer_list替換參數似乎很愚蠢。

警告信息:

test.cpp: In function ‘int main()’:
test.cpp:33:43: warning: deducing ‘const list_t’ as ‘const std::initializer_list<int>’ [enabled by default]
test.cpp:6:6: warning:   in call to ‘bool in_list(const elem_t&, const list_t&) [with elem_t = int, list_t = std::initializer_list<int>]’ [enabled by default]
test.cpp:33:43: warning:   (you can disable this with -fno-deduce-init-list) [enabled by default]

當被in_list(3, {1, 2, 3, 4, 5});

編輯:顯然推斷模板參數作為initializer_list是根據我的GCC版本( 引用 )的工作草案的擴展。 所以新問題:這仍然是最終c ++ 11標准的延伸嗎? 如果是這樣,這意味着我需要為符合標准的代碼添加第二個函數。 感謝你的幫助!

EDIT2:GCC 4.7似乎刪除了編譯器方言標志,因此問題似乎已經解決,但我不知道它是如何解決的。

使用@Ben Voigt在其他答案的評論中所說的,我收集了一些相關的標准引用:

§14.5.6.2

功能模板可以使用其他功能模板和普通(非模板)功能重載。 普通函數與函數模板無關(即,它永遠不會被認為是特化 ), 即使它與可能生成的函數模板特化具有相同的名稱和類型

因此,排除函數模板特化作為你正在做的事情,因為即使兩個函數模板重載可能潛在地生成相同的函數,它也不是特化。 所以它超載了。

這種專業化是不同的功能,不違反一個定義規則(3.2)。

所以它們是不同的功能,這就是為什么它沒有錯誤。

§14.5.6.2.1

如果函數模板被重載,則函數模板特化*的使用可能不明確,因為模板參數推導(14.8.2)可能將函數模板特化與多個函數模板聲明相關聯。

這是我們已經看到的啟動,即in_list(a, b) ,其中binitializer_list似乎與兩個函數模板匹配。

(*請注意,“函數模板特化”這里並不意味着專門化一個函數模板,它意味着一個已經用類型實例化的函數模板。所以使用template<typename T> f(); f<int>()是一個功能模板專業化。)

所以我們使用所謂的重載函數模板的部分排序來解決這個問題:

在以下上下文中使用重載函數模板聲明的部分排序來選擇函數模板特化引用的函數模板:

- 在重載解析期間調用函數模板專門化(13.3.3);

- 當采用功能模板專業化的地址時;

- 當選擇放置運算符delete作為函數模板時,選擇特殊化以匹配放置運算符new(3.7.4.2,5.3.4);

- 當朋友函數聲明(14.5.4),顯式實例化(14.7.2)或顯式特化(14.7.3)引用函數模板特化時。

好的,這就是部分訂購的時候。 這就是它的作用:

部分排序通過依次轉換每個模板(參見下一段)並使用函數類型執行模板參數推導來選擇兩個函數模板中哪一個比另一個更專業。 演繹過程確定其中一個模板是否比另一個模板更專業。 如果是這樣,則更專業的模板是由部分排序過程選擇的模板。

然后你進入了一個漫長而費力的過程,確定哪個模板更專業,如果你願意,你可以閱讀,但它真的很復雜,我可能根本不理解(加上,我沒有足夠的寫下來的時間:))。

這不是局部的說明。 你正在做的是重載功能。

暫無
暫無

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

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