将已知大小的参数的向量应用于虚拟可变参数函数

问题描述 投票:1回答:2

在下面的代码示例中,我将通过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++ variadic-templates virtual variadic-functions
2个回答
0
投票

使用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;
} 

演示:https://godbolt.org/z/ZGroAH


0
投票

以下,我不确定std::apply的用法...>

我在使用std::apply()时看到两个问题

(1)std::apply()要求std::tuple或类似参数作为第二个参数。对于“或类似”,我的意思是“或std::arraystd::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);
© www.soinside.com 2019 - 2024. All rights reserved.