3

Boostライブラリのコードを調べているところ、次の奇妙な構造体の定義が見つかりました。

struct add_ints_only
{
    template<typename T>
    struct result;

    template <typename State, typename T>
    struct result<add_ints_only(State, T)> // what's going on here?
    {
        typedef typename boost::remove_const<
            typename boost::remove_reference<State>::type>::type type;
    };

    template <typename State, typename T> 
    State
    operator()(State const& state, T const& /*x*/) const
    {
        return state;
    }

    int
    operator()(int state, int x) const
    {
        return x + state;
    }
};

それはなんのためですか?

4

2 に答える 2

3

Boost.Fusionのものかそれに似たものを探していると思います。

特に、add_ints_onlyは、ポリモーフィック関数オブジェクトの概念のモデルです。

ポリモーフィック関数オブジェクトは、オーバーロードされているか、テンプレートである可能性のあるポリモーフィックoperator()を提供します。operator()の結果タイプは、パラメータータイプによって異なる場合があります。

これは、ネストされた::result_typeを提供するSTLのAdaptableUnaryFunctionの概念に似ています。

ただし、ポリモーフィック関数オブジェクトの結果タイプは、operator()に渡される引数タイプによって異なる場合があります。したがって、operator()の引数の型に基づいて結果型を取得するには、単一の::result_typeよりも強力な機能を使用する必要があります。

template <typename State, typename T>
struct result<add_ints_only(State, T)> // ...

この構文は、クラスの部分的な特殊化です。

add_ints_only(State, T)

add_ints_onlyを返し、StageとTをパラメーターとして受け取る関数のタイプです。

それ自体、このタイプは意味がありません-add_ints_onlyを返すつもりはありません。これは、引数を渡す型の便利な形式です。add_ints_only関数の呼び出しのように見えます。また、さまざまな数の引数に特化することができます。

仕組みは次のとおりです。

ライブデモ

#include <boost/utility/result_of.hpp>
#include <typeinfo>
#include <iostream>
#include <ostream>

using namespace std;

struct PolymorphicFunctionObject
{
    template<typename T> struct result;

    template<typename Arg>
    struct result< PolymorphicFunctionObject(Arg) >
    {
        typedef Arg type;
    };

    template<typename Arg1,typename Arg2>
    struct result< PolymorphicFunctionObject(Arg1,Arg2) >
    {
        typedef Arg2 type;
    };

    template<typename Arg>
    Arg operator()(Arg t) const
    {
        return t;
    }

    template<typename Arg1,typename Arg2>
    Arg2 operator()(Arg1 t1,Arg2 t2) const
    {
        return t2;
    }
};

int main()
{
    cout << typeid
    (
        PolymorphicFunctionObject::result< PolymorphicFunctionObject(int) >::type
    ).name() << endl;
    // Output is - int

    cout << typeid
    (
        PolymorphicFunctionObject::result< PolymorphicFunctionObject(char,double) >::type
    ).name() << endl;
    // Output is - double

    // -----------------
    // Or using boost::result_of, which queries ::result internally:

    cout << typeid
    (
        boost::result_of< PolymorphicFunctionObject(short) >::type
    ).name() << endl;
    // Output is - short

    cout << typeid
    (
        boost::result_of< PolymorphicFunctionObject(char,float) >::type
    ).name() << endl;
    // Output is - float

    // ------------------
    // Or using C++11 decltype:
    cout << typeid
    (
        decltype( PolymorphicFunctionObject()( long() ) )
    ).name() << endl;
    // Output is - long

    cout << typeid
    (
        decltype( PolymorphicFunctionObject()( long(),unsigned() ) )
    ).name() << endl;
    // Output is - unsigned int

}

ご覧のとおり、結果タイプのクエリ構文は次のとおりです。

boost::result_of< PolymorphicFunctionObject(short) >::type
boost::result_of< PolymorphicFunctionObject(char,float) >::type

通常の関数呼び出しに似ています。

PS C ++ 11では、結果のタイプを自動的に取得するために使用できるdecltypeが存在するため、このようなものは必要ありません。例えば:

decltype( PolymorphicFunctionObject()( long(),unsigned() ) )
于 2012-11-08T12:02:07.657 に答える
3

result関数型に部分的に特化していますadd_ints_only(State, T)

add_ints_only目的は、ファンクターが特定の引数タイプで返すタイプを知りたいコードが、次のように記述して照会できるようにすることです。

typedef typename add_ints_only::result<add_ints_only(arg1_type, arg2_type)>::type
  result_type;

例えば

template<typename U, typename V> void foo(U u, V v) {
  typename add_ints_only::result<add_ints_only(arg1_type, arg2_type)>::type
    result = add_ints_only()(u, v);
}

operator()これは、引数の型に応じて異なる型を返すことができるファンクターに役立ちます。

于 2012-11-08T11:56:07.917 に答える