关于std :: function类定义的问题

时间:2017-10-11 07:34:17

标签: c++ c++11 std-function

我看到它的源代码(Mac XCode,/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional)是

template<class R, class... ArgTypes>                                                                                                            
class function<R(ArgTypes...)>
  : public unary_function<T1, R>      // iff sizeof...(ArgTypes) == 1 and
                                      // ArgTypes contains T1
  : public binary_function<T1, T2, R> // iff sizeof...(ArgTypes) == 2 and
                                      // ArgTypes contains T1 and T2
{...};

这里我有两个问题:

  1. 拥有

    是否合法

    class C : public A : public D {}

  2. ?这似乎是非法的,但std :: function的源代码确实编译。为什么呢?

    1. 这是什么

      template<class A, B> class foo<A(B)> //Can we have "<A(B)>" here? What's its meaning? {...}

    2. 意思?作为一个只熟悉C ++ 98的老人,我不理解class foo<A(B)>,我认为类型参数列表<...>只能出现在{{1}之后用于模板定义。顺便说一句,我知道template可以是一种函数类型。

      更新1: 感谢@Chris Drew指出问题1的代码片段来自(大)评论,因此它是一种伪代码。请忘记它。所以问题一个消失了。但问题二仍然存在。

      更新2: 我是说这个

      A(B)

      不是

      class foo<A(B)> //Can we have "<A(B)>" here? What's its meaning?

      上述class foo<A(B)> //Can we have "<...>" here? What's its meaning?实际上是<...>的捷径。我很抱歉误导了。

      我认为如果<A(B)>实际上是函数类型,那么它应该是

      A(B)

      其中template<F> class foo {...} F,根据我的C ++ 98知识和

      A(B)

      似乎不对。

3 个答案:

答案 0 :(得分:2)

  

作为一个只熟悉C ++ 98的老人,我不理解类foo,我认为类型参数列表&lt; ...&gt;只能出现在模板定义的模板之后。顺便说一句,我知道A(B)可以是函数类型。

类模板部分特化的语法:

template<class T> struct A {}; // primary class template declaration
template<class Whatever1,class Whatever2> struct A< /*whatever*/ > {}; // class template partial specialization

其中/*whatever*/是相对于用于匹配它的主类模板声明的模板参数列表。

换句话说,只要您的类模板A使用某些参数T1,...进行实例化,编译器就会同时考虑A的主要定义及其所有可见的部分特化{ {1}},试图匹配T1,......&#39;到某事&#39;根据功能模板扣除规则。如果没有找到macthes,则使用主要def;否则,使用最佳匹配候选(如果唯一)。

答案 1 :(得分:1)

1)这是语法错误,:应仅出现在基类列表中的第一项之前,然后应使用,

template<class R, class... ArgTypes>
class function<R(ArgTypes...)>
:   public unary_function<T1, R>    // iff sizeof...(ArgTypes) == 1 and
                                    // ArgTypes contains T1
,   public binary_function<T1, T2, R> 

实际上,它更像是您在不完整时发布的代码段。

2)它是function模板类专业化的模板参数包

template<typename TSome, typename TOther> class
t_Foo{ ... };

// specialization for cases when TSome is the same as TOther
template<typename T> class
t_Foo<T, T>{ ... }; // now we have <...> after template keyword and after template name as well

答案 2 :(得分:1)

  

拥有class C : public A : public D {}

是否合法

之前从未见过,而且gcc没有编译它。有,如所见 您发布的代码的注释,如果使用编译条件,SFINAE或仅仅是过载。 gcc上的实现类似于:

  template<typename _Res, typename... _ArgTypes>
    class function<_Res(_ArgTypes...)>
    : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>
      ... code continues here ...

其中_Maybe_unary_or_binary_function像这样重载:

  /**
   * Derives from @c unary_function or @c binary_function, or perhaps
   * nothing, depending on the number of arguments provided. The
   * primary template is the basis case, which derives nothing.
   */
  template<typename _Res, typename... _ArgTypes>
    struct _Maybe_unary_or_binary_function { };

  /// Derives from @c unary_function, as appropriate.
  template<typename _Res, typename _T1>
    struct _Maybe_unary_or_binary_function<_Res, _T1>
    : std::unary_function<_T1, _Res> { };

  /// Derives from @c binary_function, as appropriate.
  template<typename _Res, typename _T1, typename _T2>
    struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
    : std::binary_function<_T1, _T2, _Res> { };
  

这是什么

template<class A, B>
class foo<A(B)> //Can we have "<...>" here? What's its meaning?
{...}

如果您希望使用以下函数语法编写模板实例,则通常使用它:

foo< void( int ) > f;

是的,你可以在任何地方使用...

template <typename RETVAL, typename ... PARMS>
class Func<RETVAL(PARMS...)>
{
};

int main()
{
    Func<void(int, float)> f;
    Func<int()> f1;
    Func<float( std::string )> f2;
}

更新

  

我认为如果A(B)实际上是一个函数类型,那么它应该是

template<F>
class foo {...}

它不是function type本身,它只是一种使用函数语法来定义模板参数的方法/语法。如果您将F用作函数类型,则可以将其设置为模板模板。但这对任何事情都无济于事,因为在使用该类型的类中,您必须访问定义的每个参数。如果此处只有F,则只能将此F转发到另一个模板,因为您无法访问模板类本身内的F的返回值和参数。那有什么好处呢?

更新:

如果要实现一个模板,该模板将模板作为参数,该模板本身采用函数参数,您可以执行此操作。我列出了普通模板,模板模板中的所有变体以及功能类型的所有变体。希望有所帮助:     //定义标准模板类     模板     class Templ {};

// define one with template template parameter
template < template <typename> class TEMPL >
class TemplTempl {};

// and now to catch a function type
template <typename RETVAL, typename ... PARMS> class Func;

template <typename RETVAL, typename ... PARMS>
class Func<RETVAL(PARMS...)>
{
    public:
        static void Do() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

// and how to define a template which takes a template which takes a function type parameter?
template < template < typename RETVAL, typename ... PARMS > class F>
class FuncTempl{};

template < template < typename , typename ... > class F, typename RETVAL, typename ... PARMS >
class FuncTemplUser
{
    static void Do() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

template < template < typename , typename ... > class F, typename RETVAL, typename ... PARMS >
class FuncTemplUser< F, RETVAL(PARMS...)> : public F<RETVAL(PARMS...)>
{
    public:
    static void Do() { std::cout << __PRETTY_FUNCTION__ << std::endl; F<RETVAL(PARMS...)>::Do(); }
};



int main()
{
    // using the standard templates
    Templ<int> n1;
    // and the template which takes a template as parm
    TemplTempl<Templ> n2;

    // now use one with function type
    Func<void(int, float)> f;
    Func<void(int, float)>::Do();

    FuncTempl<Func> f2;

    FuncTemplUser<Func, void(int)> f3;
    f3.Do();
}

正如您所看到的,FuncTempl正在采用一个模板,该模板本身稍后可以使用该函数类型。这正是您认为F将会如此。