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

huangapple go评论75阅读模式
英文:

How to use a base class template member function in derived?

问题

The error you're encountering seems to be related to the usage of templates and member function inheritance. Without the complete context of your code, it's a bit challenging to pinpoint the exact issue. However, based on the provided information, it appears that the problem lies in the mismatch between the member function signatures in the base class and the derived class.

In the class B, you're trying to call the generate_values function from the base class A, but the error message indicates that there's no matching member function for the call. The issue might be with the template parameters or the std::function signature mismatch.

Ensure that the generate_values function signature in class A and class B matches exactly, including the template parameters and std::function signature. Also, make sure that the inner_generation function in class B has the correct return type and parameters as expected by the std::function in the generate_values function.

Additionally, ensure that you are using the correct scope resolution operator (::) to access the member functions from the base class within the derived class.

Without seeing the complete code and the context in which these classes are used, it's challenging to provide a more specific solution. I recommend carefully checking the function signatures, template parameters, and scope resolution to resolve the issue.

英文:

how to use a base class template function in a derived case?

Example:

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);
};

Compiling use Clang I get the following error:

 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)

I am not sure what is the issue.

I hope someone could guide me.

Originally, I had the function with same name, it was only finding the one in class B. I have then changed the names it is still not found. I am not sure is that due to the template.

答案1

得分: 0

std::function在使用时相对昂贵且不够灵活 - 如果您选择使用另一个模板参数,将更加高效、灵活,甚至可以获得更简单的代码:

class A
{
protected:
    template<typename F, typename... Args>
    std::vector<torch::Tensor> generate_value
    (
        size_t generated_points, // 不受引用的好处...
        F&& f // 要执行的函数/仿函数
        Args&&... args // 允许完美转发
    )
    {
        f(std::forward<Args>(args)...);
    } 
};

std::vector<torch::Tensor> B::generate_values(size_t generated_points, size_t column)
{
    return generate_values
    (
        generated_points,
        // 只需使用lambda,更加方便:
        [this](size_t column) { return inner_generation(column); },
        // 虽然`bind`的结果也是有效的...
        column // 还有参数...
    );
}

虽然如果使用lambda表达式(或者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); }
        // 或者使用默认绑定:
        //[=] { return inner_generation(column); }
    );
}

选择哪一个?主要是个人口味问题 - 除非您想多次使用不同变量执行相同操作,那么前一种变体有优势,因为不需要创建多个lambda:

std::vector<torch::Tensor> B::generate_values
(
    size_t generated_points,
    size_t column1,
    size_t column2 // 现在多了一个...
)
{
    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);
    // 合并两者,创建差异或执行适当的操作...
    return ...;
}

这个后者的示例在您的具体情况下可能没有意义,但在其他情境下可能会有用;)

顺便提一下:仅供解释之用,问题的原始变体因为bind的结果和lambda都不是std::function对象,因此不匹配您的模板参数。您可以通过显式创建std::function对象来解决:

return A::generate_values
(
    generated_points,
    std::function([this](size_t const& column) { return inner_generation(column); }),
    // 或者使用`bind`,虽然占位符需要明确指定模板参数:
    //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…)。

英文:

std::function is rather expensive in usage and little flexible – if you go along with yet another template parameter you are more efficient, more flexible and even get simpler code:

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

std::vector&lt;torch::Tensor&gt; B::generate_values(size_t generated_points, size_t column)
{
    return generate_values
    (
        generated_points,
        // simply use a lambda, it&#39;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...
    );
}

Though if using lambdas (or std::bind as well, if you bind the values directly instead of using place holders) you don't even need additional parameters:

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

std::vector&lt;torch::Tensor&gt; 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); }
    );
}

Which one to choose? Well, a matter of personal taste mainly – unless you want to do the same multiple times with different variables, then the former variant is of advantage for not having to create multiple lambdas:

std::vector&lt;torch::Tensor&gt; 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 ...;
}

This latter example might not be meaningful in your concrete case, but might come into play in other scenarios 如何在派生类中使用基类模板成员函数?

Side note: Just for explanation: The original variant fails for neither the result of bind nor a lambda actually being a std::function object, thus not matching your template parameter. You can solve by creating the std::function object explicitly:

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

Note, too, that in the original code of the question the return types of the std::function instantiations do not match either (first int, then torch::Tensor – unless torch::Tensor happens to be a typedef for int…).

huangapple
  • 本文由 发表于 2023年5月22日 16:02:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定