2013-04-01 61 views
4

下面的簡單代碼編譯罰款模板友元函數查找

class A { 
    int x[3]; 
public: 
    A() { x[0]=1; x[1]=2; x[2]=3; } 
    friend int const&at(A const&a, unsigned i) noexcept 
    { 
    return a.x[i]; 
    } 
    friend int foo(A const&a, unsigned i) noexcept 
    { 
    int tmp = at(a,i); 
    return tmp*tmp; 
    } 
}; 

但如果朋友們製作的模板

class A { 
    int x[3]; 
public: 
    A() { x[0]=1; x[1]=2; x[2]=3; } 

    template<unsigned I> 
    friend int const&at(A const&a) noexcept 
    { 
    static_assert(I<3,"array boundary exceeded"); 
    return a.x[I]; 
    } 

    template<unsigned I> 
    friend int foo(A const&a) noexcept 
    { 
    int tmp = at<I>(a); // <- error: use of undeclared identifier 'at' 
    return tmp*tmp; 
    } 
}; 

查找規則的改變和鐺抱怨與所述錯誤,但gcc和icpc不。誰是對的(C++ 11)?以及如何獲取叮噹的代碼?

+0

有你聲明的功能'friend'理由嗎? –

+1

嘗試'::在(a)',但你不應該。 – David

+0

@JoachimPileborg當然(這裏的代碼只是一個簡單的例子,沒有這樣的理由可能存在),這就是問題的關鍵。 – Walter

回答

4

解決方法是單獨的聲明和定義:

class A { 
    int x[3]; 
public: 
    A() { x[0]=1; x[1]=2; x[2]=3; } 

    template<unsigned I> 
    friend int const&at(A const&a) noexcept; 

    template<unsigned I> 
    friend int foo(A const&a) noexcept; 
}; 

template<unsigned I> 
int const&at(A const&a) noexcept 
{ 
    static_assert(I<3,"array boundary exceeded"); 
    return a.x[I]; 
} 

template<unsigned I> 
int foo(A const&a) noexcept 
{ 
    int tmp = at<I>(a); 
    return tmp*tmp; 
} 
+0

有趣。爲什麼? –

+0

@DrewDormann:因爲Xeo在這個問題的評論中寫了什麼。 (btw,+1) –

+0

這是否意味着clang是正確的,而另一個編譯器是錯誤的? – Walter