2014-09-30 45 views
3

我想通過比較Visual Studio的輸出與GCC的輸出來調試我通過Visual Studio得到的問題,但我似乎無法得到在Ideone中編譯的代碼的極簡化版本:Ideone中的SFINAE問題?

#include <exception> 
#include <iostream> 

template <int x> 
struct foo {}; 

template <> 
struct foo<0> { using type = int; }; 

template <typename Foo> 
struct bar 
{ 
    bar(void) {} 

    template <typename = typename Foo::type> 
    bar(const bar &) {} 
}; 

int main(void) 
{ 
    bar<foo<1>> x; 
} 

上面給我的錯誤,當我嘗試使用Ideone運行它:

prog.cpp: In instantiation of ‘struct bar<foo<1> >’: 
prog.cpp:21:17: required from here 
prog.cpp:16:5: error: no type named ‘type’ in ‘struct foo<1>’ 
    bar(const bar &) {} 

從我的理解,未能取代Foo::type不應導致編譯錯誤。請注意,使複製構造函數bar(const bar &) { typename Foo::type x; }允許程序編譯得很好。我試圖以與std::enable_if完全相同的方式使用此模板,這在使用類的任何地方時也會導致編譯錯誤 - 而不僅僅是複製構造函數。這是正確的行爲?我相當確定它不是,但我一直認爲Ideone在後端使用GCC ...

回答

4

是的,這種行爲是正確的。

當功能模板重載決議(允許編譯器放棄專門化而不會發出錯誤)推斷模板參數時適用SFINAE。因爲拷貝構造函數需要嵌套式Foo::type,不存在時存在的bar模板根本不能被實例化,:

在你的情況沒有重載解析過程中出現錯誤,但模板實例化過程中模板參數是foo<1>

爲了您的最後一點,如果你聲明:

template <typename Foo> 
struct bar 
{ 
    bar(void) {} 

    bar(const bar &) { typename Foo::type x; } 
}; 

它編譯罰款,只要你不調用拷貝構造函數。 使用複製構造函數將導致相同的編譯錯誤:

bar<foo<1>> x2 = x; // Error 
+0

這有點奇怪而且不受歡迎,但無論如何。無論如何,雖然沒有直接提供解決方案,但你幫助我自己到達那裏。用我需要的更改編輯的答案 – Duncan 2014-09-30 02:44:34

+0

編輯:我之前添加的內容實際上並不適用於這種情況,但確實適用於我的整體情況。 – Duncan 2014-09-30 04:05:34