template constructor vs copy-constructor part2
- 以下のコードはtest1でassertion failedとなる
- (2)は、'T=D'なので、暗黙に生成された(1)とのオーバーロード解決に勝利する
- test2では、(3)がB型にキャストすることによって(1)を優先するようにしているのでassertion failedにならない
- 何が問題かと言うと、VC++は、このstatic_castの抜け落ちたかのように動作するcopy-constructorを生成することがあるらしい (そのときはtest1と同様に(2)が呼ばれる)
- これはたぶんVC++のバグだと思う (12.8/8)
- このために、boost::base_from_memberでCopyableなクラスを作ることはできない
- 以上の話はoperator=でも全く同様
- そこで、disable_ifを使って、part1もまとめて対策しよう (ソースコード)
- これより分かりやすいのは、(3)のようにコンパイラの代わりに自分で書くこと
[]#include[] []<cassert>[]
[]struct[] []B[]
[]{[]
[]B[][]() { }[][]// implicitly-declared copy-constructor[]
[]// B(B const&); // (1)[][]template[][]< [][]class[] []T[][] >[]
[]B[][]([][]T[] []const[][]& [][]x[][]) [][]// (2)[]
[] {[]
[]assert[][]([][]false[][]);[]
[] }[][]};[]
[]struct[] []D[][] : [][]B[]
[]{[]
[]D[][]() { }[][]D[][]([][]D[] []const[][]& [][]other[][]) : [][]// (3)[]
[]B[][]([][]static_cast[][]<[][]B[] []const[][]&>([][]other[][]))[]
[] { }[]
[]};[]
[]void[] []test1[][]()[]
[]{[]
[]D[] []d[][];[]
[]B[] []b[][]([][]d[][]); [][]// assertion failed[]
[]}[]
[]void[] []test2[][]()[]
[]{[]
[]D[] []d1[][];[]
[]D[] []d2[][]([][]d1[][]); [][]// OK[]
[]}[]