2013-09-25 33 views
1

這是關於涉及默認參數 扣除/替換的測試用例。測試用例可以概括爲:3.3中的模板默認Arg替換失敗

template <class T, class = typename T::I>h(T){} 

template <class T, class = typename T::I>j(T){} 

class A 
{ 
    typedef int I; 
    friend void h<A>(A); 

}; 

int main() 
{ 
    A a; 
    h(a); 
    j(a); 
} 

GCC-4.8.1函數J拋出錯誤,因爲它已經沒有被宣佈的朋友,也不是私有的A級,因此違反了私有成員,我的訪問規則(這是有效的)。 gcc不會爲函數h拋出錯誤,因爲它已被聲明爲A類的朋友,因此可以訪問私有成員I.

Clang爲這兩個函數拋出錯誤。錯誤的函數j(沒有聲明的朋友是有效的,如預期),但它甚至會引發錯誤,即使對於朋友函數h(錯誤:由於我是A類的私有成員,因此導致默認arg失敗)。這違反了朋友功能的可訪問性。

我檢查了代碼路徑。雖然clang能夠推斷出默認參數,但它會在進行任何替換之前檢查訪問規則,並給出錯誤。有人可以提供有關如何解決這個問題的指導嗎?

+1

嗯,我得到了一個不同的錯誤比你偏偏使用一個依賴於第一個arg的默認參數(甚至不知道這是允許的),你可以稍後在函數或類中自己定義typedef – aaronman

回答

1

您忘記了模板函數的返回類型。

這應該解決的問題:

template <class T, class = typename T::I> void h(T){} 

template <class T, class = typename T::I> void j(T){} 

上述錯誤修復後,我仍然有錯誤,因爲

  • 你宣佈私營部分的typedef。您需要公開
  • 您錯誤地聲明瞭功能好友。它有兩個模板參數(A ::我是行不通的,因爲不完全型)

完全編譯的問題是在這裏:

#include <iostream> 

// Type your code here, or load an example. 
template <class T, class = typename T::I> void h(T t){std::cout<<t.a<<std::endl;} 

template <class T, class = typename T::I> void j(T t){std::cout<<t.a<<std::endl;} 

class A 
{ 
    friend void h<A,int>(A); 
    friend void j<A,int>(A); 
public : 
    typedef int I; 
    private : 
    int a; 

}; 

int main() 
{ 
    A a; 
    h(a); 
    j(a); 
} 
+0

@aaronman OP寫了很多很好的例子,彙編。爲模板函數添加返回類型解決了問題。或者我錯了什麼問題? –

+0

謝謝。只有在公共部分定義我時纔有效。雖然我不知道爲什麼它不適用於私人聲明,因爲朋友功能也可以訪問私人成員。 – sarda

+0

@sarda我不認爲模板參數是朋友聲明的一部分。因此,他們沒有看到它。 –