奇怪的模板结构定义

时间:2012-11-08 10:44:54

标签: c++ boost syntax

我正在探索boost库代码,并发现了以下奇怪的struct定义。

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;
    }
};

它的用途是什么?

2 个答案:

答案 0 :(得分: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;

e.g。

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()参数类型返回不同类型的仿函数很有用。

答案 1 :(得分:3)

我猜你正在寻找一些Boost.Fusion的东西或类似的东西。

特别是add_ints_only是Polymorphic Function Object概念的模型。

多态函数对象提供多态运算符(),可能会重载或可能是模板。 operator()的结果类型可能因其参数类型而异。

它与STL中的Adaptable Unary Function概念类似,它应该提供嵌套的:: result_type。

但是多态函数对象的结果类型可能因传递给operator()的参数类型而异。因此,应该使用比single :: result_type更强大的功能来获取基于operator()参数类型的结果类型。

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函数的调用。它允许对不同数量的参数进行专门化。

这是如何运作的:

live demo

#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

看起来类似于普通函数调用。

P.S。在C ++ 11中,由于存在decltype,这个东西不需要,可以用来自动获取结果类型。例如:

decltype( PolymorphicFunctionObject()( long(),unsigned() ) )