2016-08-03 47 views
0

更新,感謝AlexD的回答:這個問題歸結爲語言規則的選擇成員函數重載,這是在以下問題討論:Calling a const function rather than its non-const version範圍表達重載


range-based for loop的範圍表達是與const成員函數和非const過載的呼叫,似乎非const過載被選擇。其結果是,下面的程序無法編譯:

#include <iostream> 
#include <vector> 

class foo { 
    public: 
     const std::vector<int>& get_numbers() const { return numbers; } 
    protected: 
     std::vector<int>& get_numbers() { return numbers; } 
    private: 
     std::vector<int> numbers; 
}; 

int main() { 
    foo f; 
    for (int x : f.get_numbers()) std::cout << x << std::endl; 
} 

診斷信息從GCC 5.3:

error: ‘std::vector<int>& foo::get_numbers()’ is protected

const版本的get_numbers()可用,可用於。我們可以迫使它通過使用const參考foo實例中使用,如:

int main() { 
    foo f; 
    const foo& g = f; 
    for (int x : g.get_numbers()) std::cout << x << std::endl; 
} 

有沒有更好/更簡單的方法來告訴它可以而且應該使用const成員函數重載的編譯器,沒有明確提出const引用該對象?

有一些similar questions有關使for循環使用基於範圍的const迭代器,但我還沒有發現有關使循環的範圍表達式const選擇函數重載的目的的任何問題。

+0

我相信這是因爲'f'聲明爲'foo f;'而不是'const foo f;'這就是爲什麼非常量重載函數被選爲const的原因。我的問題是爲什麼你需要'getNumbers()'公共和私人? – DimChtz

+0

避免任何私人/受保護的getter/setter(或使用不同的名稱) –

+0

@DimChtz是的,這是問題所在。選擇的過載是函數簽名,而不是返回類型。 – doug

回答

3

但是const版本的get_numbers()可用並可以使用。

在考慮可訪問性之前選擇最佳功能。標準狀態(我的重點):

如果存在一個最佳可行函數並且是唯一的,那麼重載解析會成功並生成結果。否則重載解析失敗,調用格式不正確。 當超負荷解決方案成功時, 最佳可行功能在其使用的上下文中不可訪問(第11章),該程序爲 不合格。

+0

謝謝,就理解爲什麼選擇non-'const'過載這一點來說,這是很好的信息。但它並不完全回答是否有一種更方便的方法來選擇'const'重載而不顯式地對實例進行'const'引用的問題。 – TypeIA

+0

@TypeIA一些其他人建議與你一樣:http://stackoverflow.com/a/7287093 – AlexD

+0

謝謝,這是一個很好的鏈接,我已經將它添加到我的問題的頂部。這個鏈接問題真正成爲這個問題的核心問題,這與基於範圍的循環無關。 – TypeIA

0

一個簡單的模板函數as_const可以使演員不那麼難看。我相信這是被添加或最近被添加到標準庫。

template <typename T> T const & as_const (T const & t) { return t; } 

void f() 
{ 
    for (auto && x: as_const (y)) {} 
} 
+0

C++ 17,http://en.cppreference.com/w/cpp/utility/as_const。增加'template void as_const(const T &&)= delete;'以防止對臨時對象的懸掛引用會更安全。 – AlexD

+0

不錯,我不知道你可以刪除任意函數聲明 – nate

+0

'_T'是保留的。使用別的東西。 –