关于std::functionclass定义的问题
Questions about the definition of std::function class
我看了它的源码(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
{...};
这里我有两个问题:
合法吗
class C : public A : public D {}
?这似乎是非法的,但 std::function 的源代码确实可以编译。为什么?
这是做什么的
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:
感谢@Chris Drew 指出问题 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 {...}
根据我的 C++98 知识,F
是 A(B)
,而
template<class A, B>
class foo<A(B)>
{...}
好像不太对。
1) 这是一个语法错误,:
应该只出现在基础 classes 列表中的第一项之前,然后应该使用 ,
:
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
模板 class 专业化
的模板参数包
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
Is it legal to have 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> { };
What does this
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;
}
更新:
I think if A(B) is effectively a function type, then it should be
template<F>
class foo {...}
它不是function type
本身,它只是一种使用函数语法来定义模板参数的方式/语法。如果您将 F
用作函数类型之类的东西,则可以将其设为模板模板。但这对任何事情都没有帮助,因为在将使用该类型的 class 内部,您必须访问定义的每个参数。如果你这里只有一个F
,你只能转发这个F
到另一个模板,因为你不能访问你模板里面F
的return值和参数class 本身。那它有什么用呢?
更新:
如果你想实现一个模板,它接受一个模板作为参数,而模板本身接受一个函数参数,你可以这样做。我列出了普通模板、模板模板的所有变体,所有这些都带有函数类型。希望有所帮助:
// 定义一个标准模板 class
模板
class 圣殿{};
// 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
会是的。
As an old man who's only familiar with C++98 I don't understand class foo, and I thought a type parameter list <...> could only appear after the template for a template definition. BTW, I know A(B) can be a function type.
这是 class 模板偏特化的语法:
template<class T> struct A {}; // primary class template declaration
template<class Whatever1,class Whatever2> struct A< /*whatever*/ > {}; // class template partial specialization
其中 /*whatever*/
是相对于用于匹配它的主要 class 模板声明的模板参数列表。
换句话说,每当您的 class 模板 A
使用一些参数 T1,...
实例化时,编译器会同时考虑 A
的主要定义及其所有可见的偏特化 A<something>
,试图根据函数模板推导规则将 'T1,...' 匹配到 'something'。如果没有找到 macthes,则使用主 def;否则,使用最佳匹配候选者(如果唯一)。
我看了它的源码(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
{...};
这里我有两个问题:
合法吗
class C : public A : public D {}
?这似乎是非法的,但 std::function 的源代码确实可以编译。为什么?
这是做什么的
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: 感谢@Chris Drew 指出问题 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 {...}
根据我的 C++98 知识,F
是 A(B)
,而
template<class A, B>
class foo<A(B)>
{...}
好像不太对。
1) 这是一个语法错误,:
应该只出现在基础 classes 列表中的第一项之前,然后应该使用 ,
:
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
模板 class 专业化
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
Is it legal to have
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> { };
What does this
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;
}
更新:
I think if A(B) is effectively a function type, then it should be
template<F>
class foo {...}
它不是function type
本身,它只是一种使用函数语法来定义模板参数的方式/语法。如果您将 F
用作函数类型之类的东西,则可以将其设为模板模板。但这对任何事情都没有帮助,因为在将使用该类型的 class 内部,您必须访问定义的每个参数。如果你这里只有一个F
,你只能转发这个F
到另一个模板,因为你不能访问你模板里面F
的return值和参数class 本身。那它有什么用呢?
更新:
如果你想实现一个模板,它接受一个模板作为参数,而模板本身接受一个函数参数,你可以这样做。我列出了普通模板、模板模板的所有变体,所有这些都带有函数类型。希望有所帮助: // 定义一个标准模板 class 模板 class 圣殿{};
// 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
会是的。
As an old man who's only familiar with C++98 I don't understand class foo, and I thought a type parameter list <...> could only appear after the template for a template definition. BTW, I know A(B) can be a function type.
这是 class 模板偏特化的语法:
template<class T> struct A {}; // primary class template declaration
template<class Whatever1,class Whatever2> struct A< /*whatever*/ > {}; // class template partial specialization
其中 /*whatever*/
是相对于用于匹配它的主要 class 模板声明的模板参数列表。
换句话说,每当您的 class 模板 A
使用一些参数 T1,...
实例化时,编译器会同时考虑 A
的主要定义及其所有可见的偏特化 A<something>
,试图根据函数模板推导规则将 'T1,...' 匹配到 'something'。如果没有找到 macthes,则使用主 def;否则,使用最佳匹配候选者(如果唯一)。