Placeholder Expressionの罠

  • 型がMetafunctionであるかないかでapplyの動作が変わる
  • PlaceholderExpression自体がill-formedになり得る
  • 型でないパラメータを取る場合機能しない
  • デフォルトでは、template parameterの数が5個より多いと動作しない
    • boost::tupleなんかは駄目である
  • GCC3.4.4では、バグのためにMetafunctionにDefaultConstructibleを要求する
    • Boost1.34では対策されているが、それでも起こる場合、PlaceholderExpressionの継承を避けるといいようだ
  • これらを回避策するには、自分でMetafunctionClassを作ればいい

[]#include[] []<boost/mpl/apply.hpp>[]
[]#include[] []<boost/mpl/placeholders.hpp>[]
[]#include[] []<boost/type_traits/add_reference.hpp>[]

[]template[][]< [][]class[] []T[][], [][]class[] []U[][] >[]
[]struct[] []klass[]
[]{ };[]

[]template[][]< [][]class[] []T[][], [][]class[] []U[][] >[]
[]struct[] []has_type_self[]
[]{[]
[]typedef[] []has_type_self[] []type[][];[]
[]};[]

[]template[][]< [][]class[] []T[][], [][]class[] []U[][] >[]
[]struct[] []has_type_int[]
[]{[]
[]typedef[] []int[] []type[][];[]
[]};[]

[]template[][]< [][]class[] []T[][], [][]int[] []U[][] = [][]1[][] >[]
[]struct[] []non_type_parameter[]
[]{ };[]

[]template[][]< [][]class[] []T[][], [][]class[] []U[][] = [][]typename[] []T[][]::[][]hello[][] >[]
[]struct[] []hello[]
[]{ };[]

[]template[][]< [][]class[] []T0[][], [][]class[] []T1[][], [][]class[] []T2[][]=[][]int[][], [][]class[] []T3[][]=[][]int[][], [][]class[] []T4[][]=[][]int[][], [][]class[] []T5[][]=[][]int[][] >[]
[]struct[] []too_many_parameters[]
[]{ };[]

[]template[][]< [][]class[] []T[][], [][]class[] []U[][] >[]
[]struct[] []non_default_constructible[]
[]{[]
[]typedef[] []non_default_constructible[] []type[][];[]

[]explicit[] []non_default_constructible[][]([][]int[][])[]
[] { }[]
[]};[]

[]namespace[] []mpl[][] = [][]boost[][]::[][]mpl[][];[]

[]void[] []test[][]()[]
[]{[]
[] {[]
[] ::[][]klass[][]<[][]int[][]&, [][]double[][]> [][]x[][] =[]
[]mpl[][]::[][]apply[][]<[]
[] ::[][]klass[][]<[]
[]boost[][]::[][]add_reference[][]<[][]mpl[][]::[][]_1[][]>, [][]mpl[][]::[][]_2[]
[] >,[]
[]int[][], [][]double[]
[] >::[][]type[][]();[]
[] }[]
[] {[]
[] ::[][]has_type_self[][]<[][]int[][]&, [][]double[][]> [][]x[][] =[]
[]mpl[][]::[][]apply[][]<[]
[] ::[][]has_type_self[][]<[]
[]boost[][]::[][]add_reference[][]<[][]mpl[][]::[][]_1[][]>, [][]mpl[][]::[][]_2[]
[] >,[]
[]int[][], [][]double[]
[] >::[][]type[][]();[]
[] }[]
[] {[]
[]int[] []x[][] =[]
[]mpl[][]::[][]apply[][]<[]
[] ::[][]has_type_int[][]<[]
[]boost[][]::[][]add_reference[][]<[][]mpl[][]::[][]_1[][]>, [][]mpl[][]::[][]_2[]
[] >,[]
[]int[][], [][]double[]
[] >::[][]type[][]();[]
[] }[]
[] {[][]/*[]
[] ::non_type_parameter<int&> error =[]
[] mpl::apply<[]
[] ::non_type_parameter<[]
[] boost::add_reference<mpl::_1>[]
[] >,[]
[] int[]
[] >::type();[]
[] */[]
[]}[]
[] {[][]/*[]
[] typedef ::hello<mpl::_1> error;[]
[] */[]
[]}[]
[] {[][]/*[]
[] ::too_many_parameters<int&, double> error =[]
[] mpl::apply<[]
[] ::too_many_parameters<[]
[] boost::add_reference<mpl::_1>, mpl::_2[]
[] >,[]
[] int, double[]
[] >::type();[]
[] */[]
[]}[]
[] {[]
[] ::[][]non_default_constructible[][]<[][]int[][]&, [][]double[][]> [][]error_under_Boost_1_33[][] =[]
[]mpl[][]::[][]apply[][]<[]
[] ::[][]non_default_constructible[][]<[]
[]boost[][]::[][]add_reference[][]<[][]mpl[][]::[][]_1[][]>, [][]mpl[][]::[][]_2[]
[] >,[]
[]int[][], [][]double[]
[] >::[][]type[][]([][]1[][]);[]
[] }[]
[]}[]