- @yak_exさんのboost::recurisve_variant_関連のツイート
おっしゃる通り。だけど、そもそも、誰がなにをインスタンス化しようとしてエラーが出ているんだろう。今までboost::recursive_variant_を完全型にしてしのいできたけど、どうして完全型でなければならないのか整理してみようと思う。
さて、GCC 4.6.0 20110212において、下記のコードがコンパイルできない。
#include <map> #include <boost/variant.hpp> int main(int argc, char* argv[]) { typedef boost::make_recursive_variant< boost::blank, std::map<int, boost::recursive_variant_> >::type variant_type; variant_type v; return 0; }
コンパイルエラーから原因を読み解こうと思ったんだけど、どうしても判らなかったので断念。判りやすい例題として、次のようなものを用意した。これもコンパイルできない。
#include <boost/variant.hpp> template <typename T> struct holder { T value; }; int main(int argc, char* argv[]) { typedef boost::make_recursive_variant< boost::blank, holder<boost::recursive_variant_> >::type variant_type; variant_type v; return 0; }
コンパイルエラーが意味不明だ。もうすこし判りやすいコンパイルエラーを出してみよう。
#include <boost/variant.hpp> template <typename T> struct holder { T value; }; template <BOOST_VARIANT_ENUM_PARAMS(typename T)> inline void f(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const*) {} int main(int argc, char* argv[]) { typedef boost::make_recursive_variant< boost::blank, holder<boost::recursive_variant_> >::type variant_type; variant_type* x = 0; f(x); return 0; }
マクロが判りにくいので、展開する。
#include <boost/variant.hpp> template <typename T> struct holder { T value; }; template <typename T0, typename T1> inline void f(boost::variant<T0, T1> const*) {} int main(int argc, char* argv[]) { typedef boost::make_recursive_variant< boost::blank, holder<boost::recursive_variant_> >::type variant_type; variant_type* x = 0; f(x); return 0; }
ようやく、判りやすくなった。関数fを書き換えてみよう(まだコンパイルは通らない)。
#include <boost/variant.hpp> template <typename T> struct holder { T value; }; template <typename T0> inline void f(boost::variant<T0, holder<boost::recursive_variant_> > const*) {} int main(int argc, char* argv[]) { typedef boost::make_recursive_variant< boost::blank, holder<boost::recursive_variant_> >::type variant_type; variant_type* x = 0; f(x); return 0; }
ここまで来れば、問題は明白だ。boost::recursive_variant_を完全型にするか、holder<boost::recursive_variant_>を特殊化するしかない。ちなみに、規格のどの項目によって、この問題が規定されているのか、いまだに判らない。なぜなんだろう。
ここからは、最初のコードのコンパイルエラーから原因を読み解こうと思ったときの悪戦苦闘メモ。
In file included from /opt/morla_exp/gcc_exp/lib/gcc/x86_64-apple-darwin10.6.0/4.6.0/../../../../include/c++/4.6.0/bits/stl_algobase.h:65:0, from /opt/morla_exp/gcc_exp/lib/gcc/x86_64-apple-darwin10.6.0/4.6.0/../../../../include/c++/4.6.0/bits/stl_tree.h:63, from /opt/morla_exp/gcc_exp/lib/gcc/x86_64-apple-darwin10.6.0/4.6.0/../../../../include/c++/4.6.0/map:60, from /Users/moyu/Workspace/morla/src/recipe/recipe_recursive_variant4.cpp:1: /opt/morla_exp/gcc_exp/lib/gcc/x86_64-apple-darwin10.6.0/4.6.0/../../../../include/c++/4.6.0/bits/stl_pair.h: In instantiation of ‘std::pair<const int, boost::recursive_variant_>’: /opt/morla_exp/boost/include/boost/variant/detail/visitation_impl.hpp:260:1: instantiated from ‘typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = mpl_::int_<0>, step0 = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, boost::blank, boost::mpl::l_item<mpl_::long_<1l>, boost::recursive_wrapper<std::map<int, boost::variant<boost::detail::variant::recursive_flag<boost::blank>, std::map<int, boost::recursive_variant_>, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>, std::less<int>, std::allocator<std::pair<const int, boost::variant<boost::detail::variant::recursive_flag<boost::blank>, std::map<int, boost::recursive_variant_>, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_> > > > >, boost::mpl::l_end> > >, boost::mpl::l_iter<boost::mpl::l_end> >, Visitor = boost::detail::variant::destroyer, VoidPtrCV = void*, NoBackupFlag = boost::variant<boost::detail::variant::recursive_flag<boost::blank>, std::map<int, boost::recursive_variant_>, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_, typename Visitor::result_type = void, mpl_::false_ = mpl_::bool_<false>]’ /opt/morla_exp/boost/include/boost/variant/variant.hpp:1776:13: instantiated from ‘static typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::destroyer, VoidPtrCV = void*, T0_ = boost::detail::variant::recursive_flag<boost::blank>, T1 = std::map<int, boost::recursive_variant_>, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_, typename Visitor::result_type = void]’ /opt/morla_exp/boost/include/boost/variant/variant.hpp:1787:13: instantiated from ‘typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor(Visitor&) [with Visitor = boost::detail::variant::destroyer, T0_ = boost::detail::variant::recursive_flag<boost::blank>, T1 = std::map<int, boost::recursive_variant_>, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_, typename Visitor::result_type = void]’ /opt/morla_exp/boost/include/boost/variant/variant.hpp:1188:9: instantiated from ‘void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::destroy_content() [with T0_ = boost::detail::variant::recursive_flag<boost::blank>, T1 = std::map<int, boost::recursive_variant_>, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]’ /opt/morla_exp/boost/include/boost/variant/variant.hpp:1195:9: instantiated from ‘boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::~variant() [with T0_ = boost::detail::variant::recursive_flag<boost::blank>, T1 = std::map<int, boost::recursive_variant_>, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]’ /Users/moyu/Workspace/morla/src/recipe/recipe_recursive_variant4.cpp:10:16: instantiated from here /opt/morla_exp/gcc_exp/lib/gcc/x86_64-apple-darwin10.6.0/4.6.0/../../../../include/c++/4.6.0/bits/stl_pair.h:93:11: error: ‘std::pair<_T1, _T2>::second’ has incomplete type /opt/morla_exp/boost/include/boost/variant/variant_fwd.hpp:232:12: error: forward declaration of ‘struct boost::recursive_variant_’
流し読みすると、boost/variant/detail/visitation_impl.hppの260行めが怪しい。
BOOST_PP_REPEAT( BOOST_VARIANT_VISITATION_UNROLLING_LIMIT , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE , _ )
Boost.Preprocessor出現。これだとどこでコンパイルエラーが出ているのか判らないので、手でリピートしてみる。ちなみに、デフォルトではBOOST_VARIANT_VISITATION_UNROLLING_LIMIT = BOOST_VARIANT_LIMIT_TYPES = BOOST_MPL_LIMIT_LIST_SIZEなので20。
case (Which::value + 0): return visitation_impl_invoke( internal_which, visitor, storage, static_cast<T0*>(0), no_backup_flag, 1L); case (Which::value + 1): return visitation_impl_invoke( internal_which, visitor, storage, static_cast<T1*>(0), no_backup_flag, 1L); // 中略 case (Which::value + 19): return visitation_impl_invoke( internal_which, visitor, storage, static_cast<T19*>(0), no_backup_flag, 1L);
コンパイルエラーによると、case (Which::value + 1)のvisitation_impl_invokeのあたりで具現化されているらしい。とすると、static_cast<T1*>(0)のあたりが怪しいんだろう。T1はstep0::next::typeだ。step0がどんな型なのかはエラーメッセージに書いてある。整形して読みやすくしたT1。
T1 = boost::recursive_wrapper< std::map< int, boost::variant< boost::detail::variant::recursive_flag<boost::blank>, std::map<int, boost::recursive_variant_>, boost::detail::variant::void_, ... >, std::less<int>, std::allocator< std::pair< const int, boost::variant< boost::detail::variant::recursive_flag<boost::blank>, std::map<int, boost::recursive_variant_>, boost::detail::variant::void_, ... > > > > >
でも、なんでエラーが出るのか判らない。static_cast<T1*>(0)自体は、たとえT1がどんな型であれ、動くと思うし……。
というわけで断念。
このページへのコメント
zy6Ab8 <a href="http://lnmjrjbmkguc.com/">lnmjrjbmkguc</a>, [url=http://eknmhhwmnpaf.com/]eknmhhwmnpaf[/url], [link=http://pqjywvdctokd.com/]pqjywvdctokd[/link], http://rwnmuhgrjzky.com/