C++11 は確かに便利、なのだが現状はまだ実装が十分と言えず回避手段(workaround)を取らざるを得ない場合がある。の割には余りそういう説明を見ない、ということでせっかく書いたのでメモってみる。まぁ Boost のソースコードの中にたくさん埋まっているのだろうし、ひょっとしたら C++er は息をするように workaround が書ける人種なのかもしれないが、そこはそれ。
sorry, unimplemented: use of ‘type_pack_expansion’ in template
#include <utility> struct B { int operator()(int n) const { return n; } }; template<typename C> struct A { #if __GNUC__ == 4 && (__GNUC_MINOR__ <= 5 || __GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ == 0) template<typename ... Args> struct deduce { typedef decltype(C()(std::declval<Args&&>()...)) type; }; template<typename ... Args> typename deduce<Args...>::type operator()(Args && ... args) const { return C()(std::forward<Args>(args)...); } #else template<typename ... Args> // sorry, unimplemented: use of ‘type_pack_expansion’ in template // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48292 auto operator()(Args && ... args) const -> decltype(C()(std::forward<Args>(args)...)) { return C()(std::forward<Args>(args)...); } #endif };
このエラーメッセージが出るのは恐らくこの場合には限らないと思うのだが、type pack (Args ... みたいな展開)を tailing return type 中で使った場合。GCC bugzilla にも書いてある通り、別のクラスに切り出すことで回避できる。@iorate さんの記事([C++][Boost] C++ で一般化された on を書く)にも workaround の方法を含め書かれている。後は、GCC 4.6.1 から直っている、という情報くらいだろうか。
sorry, unimplemented: cannot expand ‘Args ...’ into a fixed-length argument list
#include <boost/fusion/include/vector.hpp> #include <boost/fusion/adapted/mpl.hpp> #include <boost/fusion/include/as_vector.hpp> #include "variadic_bridge.hpp" template<typename ... Args> struct C { #if __GNUC__ == 4 && __GNUC_MINOR__ <= 6 typename boost::fusion::result_of::as_vector< typename yak::util::variadic_to_vector<Args...>::type >::type v; #else // sorry, unimplemented: cannot expand ‘Args ...’ into a fixed-length argument list // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653 boost::fusion::vector<Args...> v; #endif };
こっちはエラーメッセージを日本語対象でググっても合っているものは tweet 1件しかヒットしない。……みんな困ってそうなものなのだが。variadic な template parameter を非 variadic な template に渡せない、というものだ。自作ヘルパ variadic_bridge.hpp を使って variadic な template parameter を MPL vector に変換して、さらに boost::fusion::vector に変換している。まぁ MPL vector まで持って来られれば後はどうとでもなるとは思うが、一応、固定長引数として Metafunction Class に渡す variadic_to_fixed も用意はしてある。こっちは GCC 4.7.0 から修正。
まとめ?
そもそも VC は 2012 でも variadic template 対応してねーよ、という時点で PP するしかないという話なのが悲しいところ。
しかし、CSS はブラウザバグとその対処、みたいなものが結構見つかるのだが C++ についてはそういうまとめみたいなものはないのだろうか。
0 件のコメント:
コメントを投稿