2014-09-19 72 views
4

如何編譯下面的代碼? PS:類型B模擬boost :: recursive_wrapper,由於相同的原因,它無法編譯。std :: pair抱怨不完整的類型

+1

** 17.6.4.8/2 **特別是,在以下情況下效果未定義:... - 如果實例化模板組件時使用了不完整類型(3.9)作爲模板參數,除非特別允許使用該組件,否則不得使用該組件。 – 2014-09-19 01:59:53

+0

@IgorTandetnik typedef本身不應該實例化'std :: pair '。 – 2014-09-19 02:00:57

+0

@ T.C .:爲什麼不呢? – jxh 2014-09-19 02:03:17

回答

7

typedef本身不是問題。編寫struct foo; typedef std::pair<foo, foo> bar;完全合法。問題是與

noexcept(std::declval<type&>() = std::declval<type>()); 

這需要編譯器執行重載分辨率operator=。由於重載解析的一部分也必須尋找可能的轉換從B&&std::pair<A, A>&&,這需要實例化std::pair<A,A>(§14.7.1[temp.inst]/P6):

類模板專業化隱式實例,如果 類類型用於上下文中,該上下文需要完全定義的對象類型,或者類類型的完整性是否會影響程序的語義 。 [注意:特別是,如果 表達式的語義取決於類別 模板專用化的成員或基類列表,則隱含地生成類模板專用化 。例如,刪除指向類類型 的指針取決於該類是否聲明析構函數,並且指向類類型的指針之間的轉換取決於涉及的兩個類之間的關係 。 - 注完]

...,並通過§17.6.4.8[res.on.functions]/P2,這個實例會導致不確定的行爲。

儘管不要求,編譯器在此上下文中以實例std::pair<A, A>由於移動賦值運算符是精確匹配(§14.7.1[temp.inst]/P7):

如果過載解析過程可以確定要調用的正確函數 而不實例化類模板定義,未指定該實例是否實際發生。

+0

我想你明白這一點。那麼如何繞過這個問題呢?你可以直接學習boost :: recursive_wrapper。 – cqdjyy01234 2014-09-19 02:13:23

+0

@ user1535111在這裏,我無法理解一些編譯器的行爲。所以[我問過一個問題](http://stackoverflow.com/questions/25925551/gcc-and-clang-implicitly-instantiate-template-arguments-during-operator-overload)。 – 2014-09-19 02:47:36

2

在另一個聲明中使用它之前,您必須實際上放入A的整個聲明。前向參考是不夠的。

+1

問題有時是不可能的。這是boost :: recursive_wrapper的值。 – cqdjyy01234 2014-09-19 02:10:08

+0

好的,對我來說,這解決了這個問題。 – donald 2016-10-18 09:41:15