Converting a function's parameter - signature from using an `std::function<T>` to a template parameter type

会有一股神秘感。 提交于 2021-01-29 16:36:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!