英文:
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
碰巧是int
的typedef
…)。
英文:
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<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...
);
}
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<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); }
);
}
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<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 ...;
}
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& 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
);
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
…).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论