rrofa
rrofa

Reputation: 11

C++ Templates for inheritance - How to use constructor?

I'm working on a C++ project where I use templates to easily switch between implementations of several inherited classes.

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?

Edit: Thank you for your quick replies. Here is the revised working example that should now 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. Please, note that I am restricted to have the method template<typename T> bool operator()(...) const otherwise I cannot interact with ceres:

#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.

Upvotes: 0

Views: 101

Answers (0)

Related Questions