2012-12-05 127 views
7

如果替換失敗涉及模板別名(,例如缺少成員類型名稱上的模板別名,如下面的代碼段中所示),是否應該觸發錯誤?模板別名和sfinae

鏘和gcc似乎對此意見不一:

// some types 
struct bar { }; 

struct foo { 
    typedef void member_type; 
}; 


// template alias 
template<class T> 
using member = typename T::member_type; 


template<class T> 
void baz(...) { } 

// only works for gcc, clang fails with: no type named 'member_type' 
// in 'bar' 
template<class T> 
void baz(member<T>*) { } 


int main(int, char**) { 

    baz<bar>(0);   // picks first 
    baz<foo>(0);   // picks second 

    return 0; 
} 

所以現在的問題是:誰是正確的,爲什麼?

感謝:-)

+0

'clang -v'說什麼?鏗鏘3.3主幹編譯代碼就好了。 – Xeo

+0

Debian clang版本3.1-8在這裏,看起來像我只需要等待。感謝您的反饋意見 ! – max

+0

你可以擺脫模板別名,只是爲了簡化一點點 – David

回答

4

根據該標準,這顯然是海灣合作委員會是正確的,因爲別名模板必須立即更換,然後正常/通常SFINAE時T知道後來應用到typename T::member_type

但目前有這個問題,請參閱http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1554

根據會議結果,似乎紅clangs行爲期望:的T取代將在別名模板(即使在typename T::member_type替代的時間範圍內完成,有一個別名無參考模板 - 它仍然需要被引用作爲參數類型模式來源的來源,如果這是它的實現方式的話)。


這與另一種情況圖案被扔掉的定義時,可能影響實例化語義

template<int I> 
void f(int x[I]); 

int main() { 
    f<0>(nullptr); 
} 

在這種情況下也是如此,在我看來,標準規範地很清楚,該參數是立即被替換爲int*,因此實例化工作。見http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1322

+5

「根據會議的結果,看起來clangs的行爲是期望的」 - 這不會完全消滅任何「EnableIf」別名嗎?它似乎非常不希望別名模板不能生成SFINAE軟錯誤。 – Xeo

+0

@Xeo是的,這將是不好的。事實上,clang trunk接受'EnableIf'別名,因此在我看來,提問者觀察到的行爲只是一個叮叮聲蟲,而wg21站點上的問題摘要只是令人困惑(恕我直言)。 –

+0

是的,我很困惑,因爲我已經評論說主幹編譯好的代碼。 – Xeo