在下面的代码示例中,我将通过foo()
方法使用已初始化的参数vect
调用具体的run()
函数。对于编译,我使用VS19和C ++ 17。在下面的内容中,我不确定我是否使用std::apply
...欢迎任何帮助;)
#include <iostream>
#include <vector>
#include <tuple>
using namespace std;
template<typename ...T>
struct Base {
vector<int> vect;
Base(){
static const std::size_t size = sizeof...(T);
for (int i = 0; i < size; i++)
vect.push_back((i+1)*(i+1)); //some initialization
}
};
template<typename ...T>
struct Derived : public Base<T...> {
virtual int foo(T...) = 0;
int lastResult;
void run() {
if (this->vect.size() > 0) {
lastResult = std::apply(foo, this->vect);
}else{
lastResult = -1;
cout << "0 arguments case" << endl;
}
}
};
struct D0 : public Derived<> {
int foo() override { return 0; }
};
struct D1 : public Derived<int> {
int foo(int a) override { return a * a; }
};
struct D2 : public Derived<int,int> {
int foo(int a, int b) override { return a + b; }
};
int main() {
D0 d0;
cout << d0.foo() << endl; // 0
//d0.run(); //vect = {}, lastResult = -1, "0 arguments case"
D1 d1;
cout << d1.foo(1) << endl; // 1
//d1.run(); //vect = {1} -> lastResult = 1
D2 d2;
cout << d2.foo(1, 2) << endl; // 3
//d2.run(); //vect = {1,4} -> lastResult = 5
cin.get();
}
使用C ++ 14中的std::index_sequence
可以帮助解决这类问题:
使用第二个版本的size_t
模板参数序列运行,并使用std::index_sequence_for
来填充它们:
template <size_t... Is>
void runImpl(std::index_sequence<Is...>) { ... }
void run() { return runImpl(std::index_sequence_for<T...>{}); }
然后,在runImpl
中,您可以扩展模板整数以将向量值作为函数参数传递:
if (this->vect.size() > 0) {
lastResult = foo(Base<T...>::vect[Is]...);
}else{
lastResult = -1;
cout << "0 arguments case" << endl;
}
以下,我不确定
std::apply
的用法...>我在使用
std::apply()
时看到两个问题
(1)std::apply()
要求std::tuple
或类似参数作为第二个参数。对于“或类似”,我的意思是“或std::array
或std::pair
”。
所以您的std::vector
不起作用。
我想您可以使用std::array
。
我提议以下Base
template<typename ...T> struct Base { std::array<int, sizeof...(T)> vect; template <int ... Is> Base (std::integer_sequence<int, Is...>) : vect {{ (Is+1)*(Is+1) ... }} { } Base () : Base{std::make_integer_sequence<int, sizeof...(T)>{}} { } };
((2)
std::apply()
的第一个参数与(非静态)方法不兼容。
但是您可以将其包装在lambda中,所以我建议
lastResult = std::apply([=](auto ... args)
{ return this->foo(args...); },
this->vect);