如何在类模板的成员函数中正确调用函数对象?正在生成Visual Studio编译器错误C2440

问题描述 投票:0回答:1

这是此问题的后续解答,发现here

现在,我可以实例化该对象。我现在收到Visual Studio C2440编译器错误...


在模板化之前的原始代码中,我有一组在std::function<double(double)>成员对象上工作的成员函数,如下所示:

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

    double evaluate() {
        auto distance = fields_.a_ - fields_.b_;  
        auto dx = distance / n_;
        return calculate(dx, fields_);
    }

private:
    double calculate(double dx, const SomeStruct& someStruct) {
        double result = 0;
        for (size_t i = 0; i < n_; ++i) {
            auto dy = func_(someStruct.a_ + i * dx);
            auto area = dy * dx;
            result += area;
        }
        return result;
    }
};

现在我的班级看起来像这样:

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 {
private:
    SomeStruct<FieldType> fields_;
    size_t n_;
    Func* func_; 

public:
    SomeClass(SomeStruct<FieldType> fields, size_t n, Func func) :
        fields_{fields}, n_{n}, func_{func}
    {}

    constexpr ValueType evaluate() {
        auto distance = fields_.a_ - fields_.b_;       
        auto dx = distance / n_;              
        return calculate(dx, fields_);
    }

private:
    constexpr ValueType calculate(ValueType dx, const SomeStruct<FieldType>& someStruct) {
        ValueType result = 0;
        for (size_t i = 0; i < n_; ++i) {
            auto dy = func_(someStruct.a_ + i * dx);
            auto area = dy * dx;
            result += area;
        }
        return result;
    }
};

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

我现在正尝试使用此类:

template<typename T>
constexpr T funcA(T x) {
    return x;
}

template<typename T>
constexpr T funcB(T x) {
    return x*x;
}

int main() {
    SomeClass a{SomeStruct{1.0, 3.0}, 1000, &funcA<double>};
    // a.evaluate();

    SomeClass b{SomeStruct{3.5, 7.5}, 2000, &funcB<double>};
    // b.evaluate();
    return 0;
}

而且我收到此Visual Studio错误...

1>------ Build started: Project: Computations, Configuration: Debug Win32 ------
1>main.cpp
1>c:\users\...\main.cpp(33): error C2440: 'initializing': cannot convert from 'initializer list' to 'Integrator<double,int,T (__cdecl *)(T)>'
1>        with
1>        [
1>            T=double
1>        ]
1>c:\users\...\main.cpp(33): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>Done building project "Computations.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

这是在我甚至调用其公共evaluate()函数之前就会生成的,该函数将调用它的私人calculate()功能...

我正在尝试解决此编译器错误,并且试图确保能够调用正确存储在此类中的函数对象,函数指针,函子,lambda ...

c++ templates compiler-errors c++17 self-invoking-function
1个回答
0
投票

问题出在数据成员Func的声明中:

Func* func_; 

它声明func_属于pointer,属于推导指南推导的类型:

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

通过使用函数的地址调用构造函数:

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

Func推导为:

Func = double(*)(double)

因此,Func*成为指向函数指针的指针:

Func* = double(**)(double)

并且无法用&funcA<double>初始化。而是,单独使用Func作为数据成员类型。


我试图确保能够调用正确存储在此类中的函数对象,函数指针,函子,lambda

要么为此使用概念,要么使用静态断言:

static_assert(std::is_invocable_v<Func&, FieldType&>, "Invalid callable");
© www.soinside.com 2019 - 2024. All rights reserved.