考虑 std::function
的声明:
template< class >
class function; /* undefined */
template< class R, class... Args >
class function<R(Args...)>;
我们有一个模板的非特化声明,它声明了一个空结构,后跟一个(部分?)特化,但与我通常看到的部分特化不同,这个仅使用类型在其模板参数中声明(不硬编码任何类型)。其目的似乎是这样当 std::function
实例化如下:
std::function<float(int, int)>
然后R
获取返回类型 ( float
) 和 (int, int)
进入参数包Args...
.
当实现我自己的内存类作为练习时,我发现我必须提供与std::function
相同的模板接口(interface)。是为了让我的内存类(class)发挥作用,因为它包含 std::function
对象,但我同样需要访问返回类型和参数,以便我可以使用函数调用运算符转发到包装函数:
template <class>
class memoiser;
template <class R, class... Args>
class memoiser<R(Args...)> {
memoiser(std::function<R(Args...)>);
R operator()(Args... args);
}
我注意到尝试删除第一个声明会导致第二个声明无法编译,如果不这样做,唯一的选择是:
template <class R, class... Args>
class memoiser { ... }
但事实并非如此,memoiser
必须实例化为 memoiser<float, int, int>
而不是memoiser<float(int, int)>
,这是不惯用的,并且当通过 decltype
传入自由函数时不起作用(而工作版本则如此)。
但是这里到底发生了什么?我知道第二个部分特化似乎需要将函数类型正确映射到模板参数,但是该语言的确切功能是什么来促进这一点?是否可以通过这种方式将更复杂的构造的其他自定义精确映射干净地构造到模板参数中?:
为什么需要空的非专用模板声明?
template <class>
class triple;
template <class X, class Y, class Z>
class triple<std::tuple<X, Y, Z>> {}; // can use this to extract X,Y,Z from the tuple instantiated with
...
triple<std::tuple<int, float, char>> butternuts = {};
最佳答案
据我所知,这是为了支持花哨或惯用的语法 std::function<float(int, int)>
,
并有效防止其他可能的语法std::function<float, int, int>
(因为我认为你无法专门研究 std::
中的某些内容)。
std::function
可能基于 Boost.Function,当时,一些编译器对花哨的语法感到困惑。
因此 Boost.Function 提供了这两个选项并调用第二个“可移植”语法。
Preferred syntax:
boost::function<float (int x, int y)> f;
Portable syntax:
boost::function2<float, int, int> f;
请参见此处:https://www.boost.org/doc/libs/1_65_1/doc/html/function/tutorial.html#idp241211680
除了更惯用之外,在当时,当您唯一的选择是使用不同数量的输入参数手动编程所有案例并且没有可变参数模板时,以这种方式实现它也可能更容易.
至于正在使用该语言的哪些功能,我会说 1) 模板特化和 2) 函数在该语言中具有明确定义的类型。
float(int, int)
是一种具体类型,可能是您无法实例化的类型,
但以同样的方式 float(*)(int, int)
也是一个具体类型,一个具体的函数指针类型或者 float(&)(int, int)
是对函数类型的引用。
关于c++ - 为什么 std::function 被实现为带有空基声明的部分模板特化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75962554/