1

私はBoost.MPLライブラリを初めて使用し、いくつかの「初心者の問題」があります

このサンプルを見てください:

template < typename F >
struct A {
   typedef boost::function_types::parameter_types<F> P;
   typedef typename boost::function_types::result_type<F>::type R;

   typedef typename boost::mpl::if_< boost::is_same< R, void >,
                                     boost::function< void ( void ) > ,
                                     boost::function< void ( R ) > >::type TTT;
   A() { }
};

int main(int argc, const char *argv[]) {
   A<int(int, float)>  ok; // working
   A<void(int, float)> compile_error; // non-working

   return 0;
}

コンパイルすると、次のようになります。

xxx.cxx: In instantiation of ‘A<void(int, float)>’:
xxx.cxx:108:25:   instantiated from here
xxx.cxx:100:77: error: invalid parameter type
‘boost::mpl::aux::wrapped_type<boost::mpl::aux::type_wrapper<void>
>::type’
xxx.cxx:100:77: error: in declaration ‘A<F>::TTT’

ここでの問題は何ですか。どうすれば解決できますか?

私の理解では、選択された部分のみがmpl::if_コンパイラによって評価されるべきです....

4

1 に答える 1

3

まず、エラーを説明するためvoidに、パラメータ リストで typedef を使用するとエラーになることに注意してください。これら 2 つの GCC バグ レポート ( 32058および9278 ) は問題を説明しており、これが標準の要件であることを指摘しています。

したがって、基本的に、標準の §8.3.5/2 によれば、これは合法です。

void foo(void);

これはそうではありませんが:

typedef void type;
void foo(type);

if_これは、そもそもが必要な理由を説明しています。typeエラーがまだ発生する理由を説明するには、MPL の遅延評価がメタ関数にのみ適用されることを理解する必要があります。メタ関数内にアクセスしない限り、評価されません。ここで、if_の引数は評価されません (メタ関数ではないため評価できません) が、インスタンス化されていないという意味ではありません。

この問題を克服するために、function遅延評価できるメタ関数にインスタンス化を埋め込むことができます。

template < typename R, typename P >
struct get_function
{
  typedef boost::function< R (P) > type;
};

template < typename F >
struct A {
    typedef boost::function_types::parameter_types<F> P;
    typedef typename boost::function_types::result_type<F>::type R;

    typedef typename 
        boost::mpl::if_< 
            boost::is_same< R, void >,
            boost::mpl::identity< boost::function< void (void) > > ,
            get_function< void, R >
        >::type::type TTT;

    A() { }
};

このように、間違ったものvoid (typedef_to_void)は決して現れません。

より良い解決策は、ケースのget_functionメタ関数を特殊化することです。void

template < typename R, typename P >
struct get_function
{
  typedef boost::function< R (P) > type;
};

template < typename R >
struct get_function< R, void >
{
    typedef boost::function< R (void) > type;
};

template < typename F >
struct A {
    typedef boost::function_types::parameter_types<F> P;
    typedef typename boost::function_types::result_type<F>::type R;

    typedef typename get_function< void, R >::type TTT;

    A() { }
};

もうif_必要ありません!

于 2011-11-24T14:46:04.733 に答える