簡體   English   中英

static_cast不按預期工作優先級

[英]static_cast not working on precedence as expected

#include <iostream>
#include <cstdint>

template<int T> void foo()
{
  std::cout << "a" << std::endl;
}

template<uint8_t T> void foo()
{
  std::cout << "b" << std::endl;
}

int main()
{
  foo<static_cast<uint8_t>(42)> ();
  foo<static_cast<int>(42)>();
  return(0);
}

知道為什么這不能按預期工作嗎?

我的gcc 4.8.1抱怨一個模糊的調用,但static_cast不應該“修復”優先級規則,在這種情況下你有兩種類型具有相同的優先級嗎?

你會認為編譯器在解析重載的函數模板時會試圖找出哪些模板更好地匹配給定的參數。 基於該假設,具有uint8_t的模板應該與具有uint8_t參數的函數調用匹配,而不是int的模板。

但這不是模板重載解析的工作原理。 模板重載決策(第14.5.6.2節)與普通函數重載決策(第13.3節)不同。 它首先建立候選模板然后,而不是試圖檢查每個匹配給定參數的程度,它只是確定兩個(或更多)候選模板中哪一個是最專業的。

請注意,這只是候選模板之間的問題。 它沒有考慮函數調用的給定參數。 (這些被考慮用於類型推導,這只是建立候選模板集的過程的一部分。)

因此它檢查uint8_t是否比int更專用,反之亦然(通常 - 不是關於手頭函數調用的給定參數)。 它基本上通過檢查是否可以(理論上)使用任何給定的uint8_t參數來填充int參數而不進行非標准轉換,反之亦然。 情況就是這樣(在兩個方向上),因此兩個模板都不比另一個更專業。 因此,模棱兩可無法解決。


標准的相關部分如下。

首先,§13.3.3確定當兩個函數模板(與兩個普通函數,或一個函數和一個模板相對)競爭函數調用時,模板重載機制用於選擇最佳:

[...]一個可行的函數F1被定義為比另一個可行函數F2更好的函數如果對於所有參數i,ICSi(F1)不是比ICSi(F2)更差的轉換序列,然后

[...] - F1和F2是功能模板特化,根據14.5.6.2中描述的偏序規則,F1的功能模板比F2的模板更專業。

那么,§14.5.6.2很長,但最相關的部分是:

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

(3)為了生成變換后的模板,對於每種類型,非類型或模板模板參數(包括其模板參數包(14.5.3))分別合成唯一類型,值或類模板,並將其替換為每次出現該參數在模板的函數類型中。 [...]

(4)使用轉換后的函數模板的函數類型,對14.8.2.4中描述的其他模板進行類型推導。

所以這里的想法是:取uint8_t模板並通過用實際的合成值替換uint8_t參數來轉換它(我猜這個值可以從實際的函數調用中獲取,但標准沒有說明)。 然后使用類型推導過程檢查轉換后的模板(作為函數調用)是否“匹配” 另一個模板(即int模板),即是否可以在沒有非標准轉換的情況下推導出另一個模板的int參數。 答案是肯定的,它可以。

然后轉到另一個方向,獲取int模板,合成一個值並嘗試“匹配” uint8_t模板,即如果uint8_t參數可以在沒有非標准轉換的情況下推斷出來。 答案是肯定的。

如果這僅在一個方向上起作用,則兩個模板中的一個必須比另一個更加專業化,並且選擇它們來解決模糊性。 如果它同時工作(如您的情況),則無法解決歧義。

注意。 整個程序實際上比較復雜,而且它在標准中的描述很長,主要原因如下:

  • 類型推導過程本身很復雜。 它確實允許某些隱式轉換(基本上,標准轉換包括一些與cv限定符相關的轉換);
  • 當一個候選參數是const-reference而另一個候選參數是非const引用時,它有一些特殊的仲裁規則,以及一些類似的情況;
  • 每個候選模板可以產生多個變換模板,尤其是當有多個模板參數被推導出來時;
  • default-arguments和模板參數包的存在使情況更加復雜。

暫無
暫無

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

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