代码之家  ›  专栏  ›  技术社区  ›  Robert

关于std::函数类定义的问题

  •  -1
  • Robert  · 技术社区  · 7 年前

    我看到了它的源代码(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 {}

    ? 这似乎不合法,但std::函数的源代码确实可以编译。为什么?

    1. 这是什么

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

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


    更新1: 感谢@ChrisDrew,他指出问题1的代码片段来自一个(大)评论,所以这是一种伪代码。请忘记它。第一个问题已经解决了。但问题二仍然存在。


    更新2: 我是说这个

    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 A(B) ,根据我的C++98知识

    template<class A, B>
    class foo<A(B)>
    {...}
    

    似乎不对。

    3 回复  |  直到 7 年前
        1
  •  2
  •   Massimiliano Janes    7 年前

    作为一个只熟悉C++98的老人,我不理解foo类,我认为类型参数列表<&燃气轮机;只能出现在模板定义的模板之后。顺便说一句,我知道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. 的主要定义及其所有可见的部分专门化 A<something> ,正在尝试匹配“T1,…”根据函数模板推导规则“某物”。如果没有找到macthes,则使用主def;否则,将使用最佳匹配候选者(如果唯一)。

        2
  •  1
  •   user7860670    7 年前

    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
    
        3
  •  1
  •   Klaus    7 年前

    合法吗 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 ...
    

    其中_可能是一元函数或二元函数重载,如下所示:

      /**
       * 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 在模板类本身内部。那么它有什么好处呢?

    更新:

    如果你想实现一个以模板为参数的模板,而模板本身又以函数参数为参数,你可以这样做。我列出了普通模板、模板模板的所有变体,以及函数类型。希望这有助于: //定义标准模板类 样板 类模板{};

    // 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 将。