簡體   English   中英

這種模板函數重載的情況使我無法理解

[英]This case of template function overloading eludes my understanding

#include <iostream>

template<typename T>
struct identity
{
    typedef T type;
};

template<typename T> void bar(T) { std::cout << "a" << std::endl; }
template<typename T> void bar(typename identity<T>::type) { std::cout << "b" << std::endl; }

int main ()
{
    bar(5); // prints "a" because of template deduction rules
    bar<int>(5); // prints "b" because of ...?

    return EXIT_SUCCESS;
}

我預計bar<int>(5)至少會產生歧義。 這里涉及到關於模板函數重載決策的瘋狂規則?

一旦我們設置了候選函數(兩個bar ),然后將其縮小到可行的函數(仍然是兩個bar ),我們必須確定最佳的可行函數。 如果有多個,我們會出現歧義錯誤。 我們采取的確定最佳步驟的步驟在[over.match.best]中列出:

[A]可行函數F1被定義為比另一個可行函數F2更好的函數,如果對於所有自變量i ,ICS i (F1)不是比ICS i (F2)更差的轉換序列,然后
- 對於某些參數j ,ICS j (F1)是比ICS j (F2)更好的轉換序列,或者,如果不是,

兩個函數都采用int類型的參數,因此兩個轉換序列都是相同的。 我們繼續。

- 上下文是用戶定義的轉換初始化[...]

不適用。

- 上下文是轉換函數的初始化,用於對函數類型的引用的直接引用綁定(13.3.1.6),[...]

不適用。

- F1不是函數模板特化,F2是函數模板特化,或者,如果不是,

bar<int>都是函數模板特化。 因此,我們進入最后一個要點,以確定最佳可行功能。

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

部分排序規則基本上歸結為我們為bar重載和在另一個重載上執行模板推導的參數合成新的唯一類型。

首先考慮“b”過載。 合成類型typename identity<Unique1>::type並嘗試對T執行模板推導。 這成功了。 最簡單的模板演繹有。

接下來,考慮“a”過載。 合成類型Unique2並嘗試對typename identity<T>::type執行模板推導。 失敗了 這是一個非推斷的上下文 - 沒有扣除可以成功。

由於模板類型推導僅在單個方向上成功,因此bar(typename identity<T>::type)重載被認為更加專業化,並被選為最佳可行候選者。


bogdan提出了另一個有趣的案例來看待部分排序。 請考慮比較:

template <typename T> void bar(T, T); // "c"
template <typename T> void bar(T, typename identity<T>::type ); // "d"

bar(5,5);
bar<int>(5, 5);

同樣,兩個候選者都是可行的(這次甚至沒有明確指定T )所以我們看看部分排序規則。

對於“c”重載,我們合成了UniqueC, UniqueC類型的UniqueC, UniqueC並嘗試對T, typename identity<T>::type進行推導。 這成功了( T == UniqueC )。 所以“c”至少與“d”一樣專業。

對於“d”重載,我們合成類型為UniqueD, typename identity<UniqueD>::type參數UniqueD, typename identity<UniqueD>::type並嘗試對T, T執行推導。 這失敗了! 參數是不同類型的! 所以“d”至少不如“c”那么專業。

因此,調用“c”重載。

暫無
暫無

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

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