I'm working on a C++ project where I use templates to easily switch between several interior orientation classes for bundle adjustment.
Combined with ceres solver, I've come across this situation where I need to create an object of the template type, however this isn't possible due to an error:
> C2665 - no overloaded function could convert all the argument types
Is there a workaround to create an object of the templated type?
The working example should reproduce my problem though it doesn't do much and make much sense. The inheritance doesn't seem to play a role here but is the reason for templating in the first place.
#define GLOG_NO_ABBREVIATED_SEVERITIES
#define NOMINMAX
#pragma warning(disable : 4996) //Windows compiler specific with Ceres version 2.1.0
#include <ceres/ceres.h>
template<typename T>
class Base
{
public:
Base()
{
X = static_cast<T>(0.0);
Y = static_cast<T>(0.0);
}
Base(const T* io_array)
{
this->X = io_array[0];
this->Y = io_array[1];
}
T doMath()
{
return X * X + Y * Y;
}
protected:
T X, Y;
};
template<typename T>
class Derived : public Base<T>
{
public:
Derived() : Base()
{
Z = static_cast<T>(0.0);
}
Derived(const T* io_array) : Base<T>(io_array)
{
this->Z = io_array[2];
}
T doMath()
{
return this->X * this->X + this->Y * this->Y + this->Z * this->Z;
}
protected:
T Z;
};
template<typename IO>
struct cRelOri {
cRelOri(const double var)
{
this->var = var;
}
template <typename T>
bool operator()(const T* const io_array, T* residual) const
{
IO io(io_array); //Error C2665
T res = io.doMath();
//This works:
//Base<T> io(io_array);
//T res = io.doMath();
//This also works:
//Derived<T> io(io_array);
//T res = io.doMath();
residual[0] = res;
return true;
}
private:
double var;
public:
static ceres::CostFunction* Create(double& var1) {
return (new ceres::AutoDiffCostFunction<cRelOri, 1, 3>
(new cRelOri(var1)));
}
};
int main()
{
double io_array[3] = { 1.0, 2.0, 3.0 };
double var = 4.2;
// Create problem
ceres::Problem problem;
ceres::CostFunction* cost_function_ro = cRelOri<Derived<double>>::Create(var);
problem.AddResidualBlock(cost_function_ro, NULL, io_array);
ceres::Solver::Options options;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
return 0;
}I've tried using pointers of a base class and then `dynamic_cast`'ing them to `IO`, which doesn't throw an error directly, but then strangely cannot convert identical (template) types any more to use the pointer.
I'm not sure if Ceres is the origin of this problem or if it's just something that's not supposed to work. I can't reproduce this problem with "standard classes" and get the feeling there might be something specific to ceres?
Any help is highly appreciated!