2012-07-12 46 views
0

更新:這個問題從價值具有用於const FooFoo不同的含義對象通過包裝類,基於entirely on strong opinions from people here此舉的實現源於之前,我一直在身邊掠過const Foo*Foo*當包裝來了,我換了Wrapper<Foo>const Wrapper<Foo>現在很清楚,機械替代沒有意義,我將需要更復雜的東西,如Wrapper<Foo>Wrapper<const Foo> ...雖然我沒有知道如何正確地寫出這些,誤解的道歉,但我會保留在這裏,因爲我實際上認爲它比許多問題更能揭示出來有沒有像std :: value_wrapper與std :: reference_wrapper並行的東西?


在尋找到this question,它似乎歸結爲平行的想法,你不能做到這一點:

const Foo defaultFoo (6502); 
const Foo theFoo (getConstFoo()); // returns const Foo for privilege reasons 
if (theFoo.getBar() < 2012) { 
    theFoo = defaultFoo; // Error. 
} 
// ...you want to do const-safe methods with theFoo... 

就像引用一個常量的值不能再定位。執行以下操作將編譯,但不會是我(在這種情況下的)將被打算:

Foo defaultFoo (6502); 
Foo& theFooRef (getFooRef()); 
if (theFooRef.getBar() < 2000) { 
    theFooRef = defaultFoo; // Not an error, but not a retarget. 
} 
// ...you want to do stuff with theFooRef... 

看來(從我的理解)是reference_wrapper可以解決此在基準情況下,像:

Foo defaultFoo (6502); 
std::reference_wrapper<Foo> theFooRef (getFooRef()); 
if (theFooRef.get().getBar() < 2000) { 
    theFooRef = std::ref(defaultFoo); 
} 
// ...do stuff with theFooRef.get() or employ implicit cast... 

我不知道是否有一個「value_wrapper」在那裏它做類似的事情。對我來說,想要一個變量來保存一個項目的值是常量正確性的常量,這並不是因爲你不會改變它。 (例如,在預訂treewalk中跟蹤當前節點,儘管只有對該樹中的節點具有const訪問權限,其中將前一節點傳遞給函數是如何獲得新節點)

如果你想成爲笨重,你可以使用std::pair<const Foo, bool>,只是忽略了bool

const Foo defaultFoo (6502); 
std::pair<const Foo, bool> theFooBool (getConstFoo(), false); 
if (theFooBool.first.getBar() < 2012) { 
    theFooBool = std::pair<const Foo, bool> (defaultFoo, false); 
} 
// ...do const-safe methods with theFooBool.first... 

但有解決這個,除了實現自己的「value_wrapper」版本的更好的辦法?

+5

我不明白。通過分配'theFoo = defaultFoo',您可以更改'theFoo'_的值。因此,聲明它爲'const'是錯誤的。如果你需要能夠改變某些東西的值,不要聲明它是'const'。如果你真的想讓'theFoo'具有const限定的特性,並且在初始化'theFoo'時需要能夠選擇一個'Foo'或者另一個',那麼使用函數或lambda表達式來封裝選擇邏輯。 – 2012-07-12 23:48:50

+5

我認爲你從根本上誤解了const的正確性_is _...另外,'getConstFoo'返回'Foo const'這一事實並不意味着'theFoo'本身必須是const;你正在執行一個邏輯副本,所以副本的源是否是const是不相關的。 – ildjarn 2012-07-12 23:49:42

+0

致@JamesMcNellis和ildjarn:赦免,但你的迴應使我平行於某人說:「如果它是一個參考,你永遠不會重新分配它,這不是參考文獻的工作方式!閱讀一本書!但是,人們會來參觀,因爲他們發現了這種發明的動機場景。所以請與我一起處理這個場景,而不是假設我*「不理解const正確性」*(!): - /我設法使用lambdas來通過一些條件初始化邏輯......但是想想pre使用const值(本身是一個包裝器)的順序遍歷的情況。 – HostileFork 2012-07-12 23:55:29

回答

1

如果你想成爲笨重,你可以使用std ::對,只是忽略布爾:

這清楚地解釋了爲什麼你想要什麼不能做,因爲this code doesn't work.我用const int,而不是const Foo,但它是一樣的想法。這條線是它打破:

theFooBool = std::pair<const Foo, bool> (defaultFoo, false); 

的拷貝賦值運算符不宣const,因爲根據定義,複製分配改變的對象。 const是當你希望對象不可更改時使用的。

當然,你可以使用std::reference_wrapper<const T>,它會給你const訪問,但允許重新綁定。當然,它不提供價值語義,但是這與您將要獲得的一樣接近。一般來說,大多數人不需要甚至不需要這個,所以它還沒有出現。

+0

感謝你給出了很好的答案,並且打破了編譯器......我得到了一些非常接近編譯的東西,但是有點被串聯起來,只是有點僞代碼來試圖表達更大的問題*「嘿,發生了什麼事情這裏」*。真正的答案是,我必須弄清楚如何將「傳遞值」包裝器對象中的「const」*放在某處,而不是包裝器本身的值。由於客戶端代碼已經匹配並自我強制執行,所以它的工作原理只是一種幻想,並沒有實際的保護。 : -/ – HostileFork 2012-07-13 00:59:18

+0

我想我在問什麼在技術上是可能的 - 一個可重新分配的包裝器,只允許const方法調用所包含的const對象。但我也許正在理解爲什麼人們不認爲這是值得實施的[我的回答爲什麼boost :: optional在包含類型是const時不會重定向](http://stackoverflow.com/a/11479925/211160)*(反饋意見)*。任何實現都不會比複製構造更有效率,而複製構造將不得不爲包裝器工作而定義。所以大多數人只會注入一個新的非const變量,並繼續生活。 (?) – HostileFork 2012-07-18 16:01:26

2

我很抱歉,如果我在這裏忽略了一些東西。但由於你的問題沒有提到它,我想知道你是否知道,並已考慮:

Foo defaultFoo (6502); 
std::reference_wrapper<const Foo> theFooRef (getFooRef()); 
if (theFooRef.get().getBar() < 2000) { 
    theFooRef = std::cref(defaultFoo); 
} 
// ...do stuff with theFooRef.get() or employ implicit cast... 
+0

謝謝; reference_wrapper對我來說是新的,我會遇到很多新的想法,因爲我[測試使用傳值封裝的常量敏感對象的建議](http://stackoverflow.com/questions/11219159 /補充可互換級類型-經由指針鑄造僅-具有到所有這些都不-)。與許多設計模式一樣,這並不容易。我提到了我認爲是造成混亂的根源 - 我不想'const包裝器'與'Wrapper ',我想'包裝器'和'包裝器',這很難計算出來怎麼寫。 : - /任何提示讚賞! – HostileFork 2012-07-13 01:04:10

+0

@HostileFork:寫一個'模板結構包裝器;'和一個部分專業化'模板結構包裝器;'? – ildjarn 2012-07-13 01:31:53

+0

@ildjarn非常感謝,我沒有想過部分模板專業化。使用這種方法,我設法得到了一些與我以前一樣的方式,但希望這種方法避免了嚴重別名/等的潛在違規。那是在那裏:https://gist.github.com/3106817 – HostileFork 2012-07-13 19:28:10