c++ 如何在派生中使用基类模板成员函数?

np8igboo  于 2023-05-24  发布在  其他
关注(0)|答案(1)|浏览(106)

如何在派生示例中使用基类模板函数?
示例:

Class A{

    protected:
       template<typename... Args>
            std::vector<torch::Tensor> generate_value(const size_t& generated_points, std::function<int(const Args&...)> function, const Args&... args);
};
class B : protected A{
   public:
      B() : A(){}
   protected:
     std::vector<torch::Tensor> generate_values(const size_t& generated_points, const size_t& column){
        return this->generate_values(generated_points, std::bind(&A::inner_generation, this, std::placeholders::_1), column);
     }

     <torch::Tensor inner_generation(const size_t& column);
};

编译使用Clang我得到以下错误:

error: no matching member function for call to 'generate_values'
        return this->generate_values(generated_points, function, column);
               ~~~~~~^~~~~~~~~~~~~~~
note: candidate template ignored: could not match 'std::function<torch::Tensor (const Args &...)>
            std::vector<torch::Tensor> generate_values(const size_t& generated_points, std::function<torch::Tensor(const Args&...)> function, const Args&... args)

我不知道是什么问题。
我希望有人能指导我。
原来,我有一个同名的函数,它只是在class B中找到一个。后来我改了名字,还是没找到。我不知道是不是因为template

zengzsys

zengzsys1#

std::function使用起来相当昂贵,而且灵活性很小-如果你沿着另一个模板参数,你会更高效,更灵活,甚至得到更简单的代码:

class A
{
protected:
    template<typename F, typename... Args>
    std::vector<torch::Tensor> generate_value
    (
        size_t generated_points, // no benefit from reference...
        F&& f // the function/functor to execute
        Args&&... args // allows perfect forwarding
    )
    {
        f(std::forward<Args>(args)...);
    } 
};

std::vector<torch::Tensor> B::generate_values(size_t generated_points, size_t column)
{
    return generate_values
    (
        generated_points,
        // simply use a lambda, it's just more convenient:
        [this](size_t column) { return inner_generation(column); },
        // though the result of `bind` would be just as valid...
        column // and the parameter...
    );
}

但是如果使用lambdas(或者std::bind,如果你直接绑定值而不是使用占位符),你甚至不需要额外的参数:

template<typename F>
std::vector<torch::Tensor> A::generate_value(size_t generated_points, F&& f)
{
    f();
}

std::vector<torch::Tensor> B::generate_values(size_t generated_points, size_t column)
{
    return generate_values
    (
        generated_points,
        [this, column] { return inner_generation(column); }
        // alternatively with default bindings:
        //[=] { return inner_generation(column); }
    );
}

选哪一个?好吧,这主要是个人品味的问题-除非你想用不同的变量多次执行相同的操作,那么前一个变体的优点是不必创建多个lambda表达式:

std::vector<torch::Tensor> B::generate_values
(
    size_t generated_points,
    size_t column1,
    size_t column2 // now one more...
)
{
    auto gen = [this](size_t column) { return inner_generation(column); };
    auto v1 = generate_values(generated_points, gen, column1);
    auto v2 = generate_values(generated_points, gen, column2);
    // union both, create difference or do whatever is appropriate...
    return ...;
}

后一个例子在您的具体案例中可能没有意义,但在其他场景中可能会起作用;)
附注:仅作说明:原始的变体失败,因为bind的结果和实际上是std::function对象的lambda都不是,因此不匹配模板参数。您可以通过显式创建std::function对象来解决:

return A::generate_values
(
    generated_points,
    std::function([this](size_t const& column) { return inner_generation(column); }),
    // alternatively with `bind`ing, though the place holder makes
    // explicitly specifying the template argument necessary:
    //std::function<torch::Tensor(size_t const&)>
    //(
    //    std::bind(&B::inner_generation, this, std::placeholders::_1)
    //),
    column
);

还要注意,在问题的原始代码中,std::function示例化的返回类型也不匹配(首先是int,然后是torch::Tensor-除非torch::Tensor恰好是inttypedef...)。

相关问题