2015-11-05 46 views
2

Consinder下面的例子:可以自動演繹添加隱式常量?

#include <iostream> 
#include <string> 

struct foo { std::string value; }; 
inline foo bar() { return { "42" }; } 

std::string my_func() { 
    auto &x = bar(); 
    ^^^^^^^^^^^^^^^^ 
    return x.value; 
} 

int main() { 
    std::cout << my_func() << std::endl; 
} 

編譯它既GCCCLANG EMIT,最有可能理所當然,同樣的錯誤:

error: invalid initialization of non-const reference of type 'foo&' from an rvalue of type 'foo'

然而,令我驚訝的是編譯和運行在VC罰款+ +2015。

  • 這是VC++ 2015的bug嗎?
  • 該標準是否規定auto可以在語句呈現程序不合格時向對象添加隱式const

回答

3

Is this a bug of VC++2015?

該標準允許實現接受不適當的擴展代碼。然而,實現仍然需要發佈診斷(這可能意味着「打開某些標誌時發出警告」)。

Does the standard dictates that auto can add implicitly constness to an object when a statement renders the program ill-formed?

沒有,標準要求auto扣除使用相同的規則模板參數推導(與初始化列表的例外)。如果T&不會接受它,那麼auto&不會。

2

不,auto不能添加常量。但是,MSVC++一直有一個擴展,非const左值引用可以綁定到右值。

我想,你可以使用/Za開關禁用這個擴展。

1

Is this a bug of VC++2015?

微軟被告往往稱之爲「功能」,但它是在一個編譯器(可以解決與/Za)的那些亂七八糟完全愚蠢的錯誤。讓我們看看爲什麼...

auto &x = bar(); 

好吧,所以你打電話給bar(),不是嗎?這產生一個rvalue,即一個沒有地址的對象。現在,您不能將lvalue(可以獲得地址的對象)參考(又名:&)綁定到rvalue。到目前爲止,這就是你的代碼非法的原因。

但是,C++語言中有一條特殊規則,允許const lvalue引用綁定到rvalue,從而有效延長其使用期限。因此,這將是有效的代碼......

const auto &x = foo(); 

編輯:BTW ...

Does the standard dictates that auto can add implicitly constness to an object when a statement renders the program ill-formed?

爲了把它在非standardese術語/簡單的英語,如果T&被拒絕,所以將auto&。 CV限定符(constvolatile)分別是而不是自動從auto推導出來。

我希望這能帶給你一些亮點!

+0

「CV-限定符('const'和'volatile')不會自動從'auto'推導出來。」不完全的。 'const int c = 1; auto&d = c;/*確定,d是const int&* /'它不會讓人想起cv-qualifiers,但是如果初始化器符合cv標準,那麼推斷它就非常令人高興 –

+0

To @ T.C。我會補充說,它甚至可以用右值:'auto&d = std :: move(c)'將會編譯。但是你沒有看到那些常量合格的rvalues。 – Brian

+0

你在做什麼?我目前與GNU/Linux一起工作,私下裏有一臺Mac,但我*擁有*來防禦「Redmond」,因爲編譯器可以自由地接受不規範的代碼作爲擴展(除了可能需要警告外,正如前面提到的那樣)。這個特定的擴展是否值得是另一個話題。例如,GCC開發者事實上一直很樂意爲其他編譯器團隊提供擴展 - 記得C++簽名?沒有我知道的「純粹的標準C++」編譯器,甚至沒有默認情況下。 –