使用可变函数作为模板参数
Use variadic function as template argument
我想让下面的代码在不改变 Child1
和 Child2
class 的情况下工作:
#include <iostream>
int triple(int a) {
return a * 3;
}
int add(int a, int b) {
return a + b;
}
template<int (*F)(int)>
class Parent {
public:
Parent(int a) {
std::cout << "constructed: " << F(a) << std::endl;
}
};
class Child1 : Parent<triple> {
public:
Child1(int a) : Parent(a) {}
};
/*class Child2 : Parent<add> {
public:
Child2(int a, int b) : Parent(a, b) {}
};*/
int main() {
Child1 child(4);
//Child2 child(5, 6);
return 0;
}
如您所见,例如,Child1
继承自已使用 triple
函数实例化的 Parent
。因此,当 Child1
被实例化为 4 时,它输出“constructed: 12
”。
相比之下,Child2
被注释掉了,因为它显然还不能工作。在主函数中,我试图将两个参数传递给 Child2
构造函数,就像底层 add()
函数所期望的那样。然而,Parent
的构造函数只接受一个参数,可能需要在它前面加上 template<typename Args...>
来解决问题。此外,Parent
class 将需要一个模板参数,如 int (*F)(Args...)
。最终,像 main 函数那样构造一个 Child2
实例应该输出“constructed: 11
”。
我怎样才能做到这一点,即创建一个模板参数,它是一个可以有任意数量参数的函数?再次请注意,Parent
class 的代码是唯一可以更改的内容。
在 C++17 中,您可以使用推导的非类型模板参数并使构造函数成为可变参数模板:
template<auto x_pointer_to_function>
class Parent
{
public:
template<typename... x_Args>
Parent(x_Args &&... args)
{
std::cout << "constructed: " << ((*x_pointer_to_function)(::std::forward<x_Args>(args)...)) << std::endl;
}
};
来不及玩了?
我提出了基于 auto
的 C++17 VTT 答案的变体,它使用 class 专业化来提取 Args...
输入类型(和 Ret
类型,如果有用的话)。
我是说
template <auto>
class Parent;
template <typename Ret, typename ... Args, Ret(*F)(Args...)>
class Parent<F>
{
public:
Parent (Args const & ... as)
{ std::cout << "constructed: " << F(as...) << std::endl; }
};
下面是一个完整的编译示例
#include <iostream>
int triple (int a)
{ return a * 3; }
long add (int a, int b)
{ return a + b; }
template <auto>
class Parent;
template <typename Ret, typename ... Args, Ret(*F)(Args...)>
class Parent<F>
{
public:
Parent (Args const & ... as)
{ std::cout << "constructed: " << F(as...) << std::endl; }
};
class Child1 : public Parent<triple>
{
public:
Child1 (int a) : Parent{a}
{ }
};
class Child2 : public Parent<add>
{
public:
Child2 (int a, int b) : Parent{a, b}
{ }
};
int main()
{
Child1 c1{4};
Child2 c2{5, 6};
}
松散的完美转发,但可以控制参数的数量(和类型)。
我想让下面的代码在不改变 Child1
和 Child2
class 的情况下工作:
#include <iostream>
int triple(int a) {
return a * 3;
}
int add(int a, int b) {
return a + b;
}
template<int (*F)(int)>
class Parent {
public:
Parent(int a) {
std::cout << "constructed: " << F(a) << std::endl;
}
};
class Child1 : Parent<triple> {
public:
Child1(int a) : Parent(a) {}
};
/*class Child2 : Parent<add> {
public:
Child2(int a, int b) : Parent(a, b) {}
};*/
int main() {
Child1 child(4);
//Child2 child(5, 6);
return 0;
}
如您所见,例如,Child1
继承自已使用 triple
函数实例化的 Parent
。因此,当 Child1
被实例化为 4 时,它输出“constructed: 12
”。
相比之下,Child2
被注释掉了,因为它显然还不能工作。在主函数中,我试图将两个参数传递给 Child2
构造函数,就像底层 add()
函数所期望的那样。然而,Parent
的构造函数只接受一个参数,可能需要在它前面加上 template<typename Args...>
来解决问题。此外,Parent
class 将需要一个模板参数,如 int (*F)(Args...)
。最终,像 main 函数那样构造一个 Child2
实例应该输出“constructed: 11
”。
我怎样才能做到这一点,即创建一个模板参数,它是一个可以有任意数量参数的函数?再次请注意,Parent
class 的代码是唯一可以更改的内容。
在 C++17 中,您可以使用推导的非类型模板参数并使构造函数成为可变参数模板:
template<auto x_pointer_to_function>
class Parent
{
public:
template<typename... x_Args>
Parent(x_Args &&... args)
{
std::cout << "constructed: " << ((*x_pointer_to_function)(::std::forward<x_Args>(args)...)) << std::endl;
}
};
来不及玩了?
我提出了基于 auto
的 C++17 VTT 答案的变体,它使用 class 专业化来提取 Args...
输入类型(和 Ret
类型,如果有用的话)。
我是说
template <auto>
class Parent;
template <typename Ret, typename ... Args, Ret(*F)(Args...)>
class Parent<F>
{
public:
Parent (Args const & ... as)
{ std::cout << "constructed: " << F(as...) << std::endl; }
};
下面是一个完整的编译示例
#include <iostream>
int triple (int a)
{ return a * 3; }
long add (int a, int b)
{ return a + b; }
template <auto>
class Parent;
template <typename Ret, typename ... Args, Ret(*F)(Args...)>
class Parent<F>
{
public:
Parent (Args const & ... as)
{ std::cout << "constructed: " << F(as...) << std::endl; }
};
class Child1 : public Parent<triple>
{
public:
Child1 (int a) : Parent{a}
{ }
};
class Child2 : public Parent<add>
{
public:
Child2 (int a, int b) : Parent{a, b}
{ }
};
int main()
{
Child1 c1{4};
Child2 c2{5, 6};
}
松散的完美转发,但可以控制参数的数量(和类型)。