【问题标题】:Converting a function's parameter - signature from using an `std::function<T>` to a template parameter type将函数的参数 - 签名从使用 `std::function<T>` 转换为模板参数类型
【发布时间】:2020-06-03 01:17:35
【问题描述】:

在我现有的代码库中,我有一个非模板类,它的构造函数具有以下声明签名...

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

我是这样使用它的:

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

上面的表示效果很好......


我正在重构我的代码,我想对我的类进行模板化,我正在尝试允许将类及其成员函数完全定义为 constexpr...

我的类的新签名应该是这样的:

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

我在这里遇到或正在努力解决两个问题或问题......

ValueType 模板参数应该是Func 模板参数的一部分...作为旁注,所有函数指针、函子、lambda 等目前都具有接受单个参数的形式T 类型的值,它们返回 T 类型的值。

另一个“更重要”的问题涉及我尝试实例化对象时...

SomeClass<double, double, ?> a{ SomeStruct{ 3.0, 5.0 }, 1000, &funcA }; 

我对函数指针的模板参数的语法感到困惑......以及能够将函数作为对象传递......

【问题讨论】:

    标签: c++ templates parameters c++17 constexpr


    【解决方案1】:

    我建议不要为构造函数指定模板参数,而是提供这样的推导指南:

    template<typename FieldType, typename ValueType, typename Func>
    SomeClass(SomeStruct<FieldType>, ValueType, Func*)
     -> SomeClass<FieldType, ValueType, Func>;
    

    然后你可以像这样调用构造函数:

    SomeClass a{ SomeStruct{ 3.0, 5.0 }, 1000, &funcA }; 
    

    这是demo

    此外,没有理由将函数存储为指针,您可以将其存储为对象。正如 cmets 中所指出的,这样做的好处是您现在也可以存储有状态的 lambda。

    这是一个demo

    【讨论】:

    • 并且不强制函数成为指针使类更有用和通用。例如,它将允许使用捕获的 lambda,如 SomeClass a{ SomeStruct{3.0, 5.0}, 1000, [multiplier](double x) { return multiplier*x; }};
    • @aschepler 这是一个很好的观点。我将其添加到答案中。
    • 现在,我能够以这种方式“实例化”一个对象......我有一个更新但相关的问题......它涉及使用此类执行的成员函数之一将调用函数指针、函数对象、函子、lambda 等的计算...现在正在生成编译器错误...
    • 我应该创建新问题吗?还是我应该编辑这个问题并将其放在新部分的原始帖子下方?
    • 尝试删除尽可能多的内容,同时保留您遇到的问题,针对新问题。
    猜你喜欢
    • 2014-11-02
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 2017-10-10
    • 2020-12-17
    • 1970-01-01
    相关资源
    最近更新 更多