2011-02-08 119 views
4

考慮下面的代碼:的C++ 0x decltype無法推斷成員變量,常量性

template <typename T> 
class B 
{ 
}; 

template <typename T> 
B<T> f(T& t) 
{ 
    return B<T>(); 
} 

class A 
{ 
    class C {}; 
    C c; 
public: 
    A() {} 

    decltype(f(c)) get_c() const { return f(c); } 
}; 

int main() 
{ 
    A a; 
    a.get_c(); 
} 

當我嘗試編譯,我得到的錯誤:

test.cpp: In member function 'B<A::C> A::get_c() const': 
test.cpp:31:46: error: conversion from 'B<const A::C>' to non-scalar type 'B<A::C>' requested 

看來,在編譯器不知道這是一個const成員函數,因此c的類型爲const C,因此錯誤地將f(c)的類型推斷爲B<C>,而不是B<const C>,這實際上就是這樣。

我在做什麼不正確,還是這是一個編譯器錯誤?我使用gcc 4.6,但4.4和4.5顯示相同的行爲。

回答

7

編譯器根據當前C++ 0x WP正確運行。見this issue report,目前正在進行。

可能最終的C++ 0x標準不會在函數名稱前的返回類型中更改您的decltype應用程序的含義。您需要將它移動到參數列表後面,使用-> decltype(f(c)),這有望在最終的C++ 0x中執行正確的操作。

0

不,decltype不應該考慮函數是否爲const,因爲它不能。同樣可以編寫不同:

typedef decltype(f(c)) return_type; 

return_type get_c() const { return f(c); } 

更正:decltype(f(c))甚至不應該編譯,因爲c也不是一成不變的。

+2

是的,它應該編譯。在未評估的上下文中,您可以訪問非靜態數據成員。 – 2011-02-08 21:32:21

+0

@Johannes,我可能是錯的,但據我記得只有在函數體內允許訪問非靜態成員。如果上面的函數被修改爲使用尾隨返回類型,那麼您可以訪問非靜態成員。 – 2011-02-08 21:52:21

+0

是的,我認爲你錯了。看到我的答案在這裏相關的問題:http://stackoverflow.com/questions/4849556/does-c0x-allow-decltype-in​​-function-signature/4850444#4850444 – TonyK 2011-02-08 21:59:58

0

f需要採用右值引用,而不是左值引用。

0

我不認爲你可以在任何你通常無法打電話的地方使用decltype。我一直無法找到標準中的任何內容,即使在任何可以使用c的地方以外,即使在decltype表達式中也可以訪問c。既然你沒有this指針,那麼你就不會做你想做的事情。這樣做至少在MSVC 2010中不起作用,並且與const無關。

我考慮使用declval來得到一個,但是你不能訪問A &。因爲A在這一點上是不完整的類型。反正我看不出你想做的事情,而不是像這樣:

decltype(f(declval<C const>())) get_c() const { ... }