问题
This is a follow up to this question found here!
Now, that I'm able to instantiate the object. I'm now getting a Visual Studio C2440 Compiler Error...
In my original code before it was templated I had a set of member functions that worked on the std::function<double(double)>
member object that looked like this:
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;
}
};
Now my class looks 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 {
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>;
I'm now trying to use the class as such:
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;
}
And I'm getting this Visual Studio error...
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 ==========
This is being generated before I even call its public evaluate()
function that will call its
private calculate()
function...
I'm trying to resolve this compiler error, and I'm trying to make sure that I'm able to invoke the function object, function pointer, functor, lambda that is stored within this class properly...
回答1:
The problem is in the declaration of data member Func
:
Func* func_;
It declares func_
to be of a pointer to the type deduced by a deduction guide:
template <typename FieldType, typename ValueType, typename Func>
SomeClass(SomeStruct<FieldType>, ValueType, Func)
-> SomeClass<FieldType, ValueType, Func>;
By calling the constructor with an address of a function:
SomeClass a{SomeStruct{1.0, 3.0}, 1000, &funcA<double>};
Func
is deduced as:
Func = double(*)(double)
Thus, Func*
becomes a pointer to a function pointer:
Func* = double(**)(double)
and that cannot be initialized with &funcA<double>
. Instead, use Func
alone as the data member type.
I'm trying to make sure that I'm able to invoke the function object, function pointer, functor, lambda that is stored within this class properly
Either use a concept for that or a static assert:
static_assert(std::is_invocable_v<Func&, FieldType&>, "Invalid callable");
来源:https://stackoverflow.com/questions/62164213/how-to-properly-invoke-a-function-object-within-a-class-templates-member-functi