问题
In my existing codebase, I have a non-template class and its constructor has the following declaration signature...
struct SomeStruct {
double a_;
double b_;
SomeStruct(double a, double b) : a_{a}, b_{b} {}
}
class SomeClass {
private:
SomeStruct fields_;
size_t n_;
std::function<double(double)> func_;
public:
SomeClass(SomeStruct fields, size_t n, std::function<double(double)> func) :
fields_{fields}, n_{n}, func_{func}
{}
};
I was using it like this:
constexpr double funcA(double x) {
return x;
}
constexpr double funcB(double x) {
return x*x;
}
int main() {
SomeClass a(SomeStruct{1.0, 5.0}, 1000, &funcA);
SomeClass b(SomeStruct{3.5, 7.7}, 2000, &funcB);
return 0;
}
And the above representation works just fine...
I'm in the process of refactoring my code and I want to template my class and I'm trying to allow the class and its member functions to be defined fully as constexpr...
The new signature of my classes ought to look like this:
template<typename Field>
struct SomeStruct {
Field a_;
Field b_;
constexpr SomeStruct(Field a, Field b) : a_{a}, b_{b} {}
};
template<typename FieldType, typename ValueType, typename Func>
class SomeClass {
SomeStruct<FieldType> fields_;
size_t n_;
// std::function<double(double)> func_; // No longer using `std::function` since I want this to be constexpr
Func* func_; // would like to save a pointer to a function, functor, function object, or lambda instead...
public:
SomeClass(SomeStruct<FieldType> fields, size_t n, Func* func) :
fields_{fields}, n_{n}, func_{func}
{}
};
There are two issues or problems that I'm having here or struggling with...
The ValueType
template argument should be a part of the Func
template argument... And as a side note, all of the function pointers, functors, lambdas, etc. currently have the form of accepting a single parameter of type T
and they are returning a value of type T
.
The other issue which is the "more important" issue involves when I try to instantiate an object...
SomeClass<double, double, ?> a{ SomeStruct{ 3.0, 5.0 }, 1000, &funcA };
I'm getting confused about the syntax for the template arguments for the function pointers... along with being able to pass in a function as an object...
回答1:
I would suggest not specifying the template parameters for the constructor, but instead provide a deduction guide like this:
template<typename FieldType, typename ValueType, typename Func>
SomeClass(SomeStruct<FieldType>, ValueType, Func*)
-> SomeClass<FieldType, ValueType, Func>;
and then you can call the constructor like this:
SomeClass a{ SomeStruct{ 3.0, 5.0 }, 1000, &funcA };
Here's a demo.
Additionally, there's no reason to store the function as a pointer, you could just store it as an object. As pointed out in the comments, this has the advantage that you can now store stateful lambdas as well.
Here's a demo of that.
来源:https://stackoverflow.com/questions/62163732/converting-a-functions-parameter-signature-from-using-an-stdfunctiont-t