C2436'{ctor}':构造函数初始化器列表中的成员函数或嵌套类

时间:2018-07-29 21:09:11

标签: c++ constructor initializer-list

我不太了解Compiler错误中的成员函数

C2436 '{ctor}': member function or nested class in constructor initializer list

使用Visual C ++

在我的SubNearestNeighbors.hpp中写:

template<typename _T>

class SubNearestNeighbors : public ompl::NearestNeighbors<_T>

{

public:

    typedef std::function<double(const _T&, const _T&)> DistanceFunction;

    SubNearestNeighbors(const ob::SpaceInformationPtr &si)
        :
        PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
    {}

    SubNearestNeighbors()// here is the member function cause the error <----
        :                // but it doesn't have any void in it?             |
        PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()                 |
    {} // error get here, it say member func. or nested class in constructor| 
       // initialize list, while compiling class template member function   | 
       //'SubNearestNeighbors<PathPlannerOMPLServer::kdRRTConnect::Motion*> |
       //::SubNearestNeighbors(void) ---------------------------------------
    ~SubNearestNeighbors()
    {

    }

    //...more other function

kdRRTConnect.cpp中的代码编写为:

PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
:
ompl::base::Planner((const base::SpaceInformationPtr &)*((base::SpaceInformationPtr*)(unsigned char*)0), "kdRRTConnect") {
    typedef std::shared_ptr < ompl::NearestNeighbors<Motion*>> nn_ptr;

    nn_ptr nn_;

    nn_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}

Output Tipp tells me that the problem of member function is SubNearestNeighbors(void)

有人可以给我小费吗,这意味着初始化成员列表中的成员函数SubNearestNeighbors(void),但实际上在SubNearestNeighbors中不存在任何空白。

1 个答案:

答案 0 :(得分:0)

感谢@ M.M和@Fei Xiang。

因为_T是在公共ompl :: nearestneighbors <_T>中定义的(这里是该类的链接:ompl.kavrakilab.org/NearestNeighbors_8h_source.html),所以仅模拟了另一个类NearestNeighborsLinear(ompl.kavrakilab.org /NearestNeighborsLinear_8h_source.html)、NearestNeighborsGNAT(ompl.kavrakilab.org/NearestNeighborsGNAT_8h_source.html)、NearestNeighborsAqrtApprox(ompl.kavrakilab.org/NearestNeighborsSqrtApprox_mpl.8):我写模板没有其他选择。

在这里,我给出了Ompl :: NearestNeighbors <_T>类的代码,我继承并覆盖了该类中的函数。

namespace ompl
 {
     template <typename _T>
     class NearestNeighbors
     {
     public:
         typedef std::function<double(const _T &, const _T &)> DistanceFunction;

         NearestNeighbors() = default;

         virtual ~NearestNeighbors() = default;

         virtual void setDistanceFunction(const DistanceFunction &distFun)
         {
             distFun_ = distFun;
         }

         const DistanceFunction &getDistanceFunction() const
         {
             return distFun_;
         }

         virtual bool reportsSortedResults() const = 0;

         virtual void clear() = 0;

         virtual void add(const _T &data) = 0;

         virtual void add(const std::vector<_T> &data)
         {
             for (const auto &elt : data)
                 add(elt);
         }

         virtual bool remove(const _T &data) = 0;

         virtual _T nearest(const _T &data) const = 0;

         virtual void nearestK(const _T &data, std::size_t k, std::vector<_T> &nbh) const = 0;

         virtual void nearestR(const _T &data, double radius, std::vector<_T> &nbh) const = 0;

         virtual std::size_t size() const = 0;

         virtual void list(std::vector<_T> &data) const = 0;

     protected:
         DistanceFunction distFun_;
     };
 }

在这里,我很难举一个最小的例子。有关更多详细信息,请完成我的SubNearestNeighbors类:

template<typename _T>
class SubNearestNeighbors: public ompl::NearestNeighbors<_T>
{
public:

SubNearestNeighbors(const ob::SpaceInformationPtr &si)
:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(){}


SubNearestNeighbors()
:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(){}

~SubNearestneighbors()
{

}
// All the functions below are just override all of the pure virtual function in ompl::NearestNeighbors<_T>
void clear()
{
motions.clear();
}
void list(std::vector<_T> &data) const
{
        typename PathPlannerOMPLServer::kdRRTConnect::Motion;
        data = motions;

}
std::size_t size() const
{
    return motions.size();
}
void add(const _T &data)
{
    typename PathPlannerOMPLServer::kdRRTConnect::Motion;

    motions.push_back(data);
}
bool remove(const _T &data)
    {
        typename PathPlannerOMPLServer::kdRRTConnect::Motion;

        if (!motions.empty())
            for (int i = motions.size() - 1; i >= 0; --i)
                if (motions[i] == data)
                {
                    motions.erase(motions.begin() + i);
                    return true;
                }
        return false;

}
_T nearest(const _T &data) const
{

    typename PathPlannerOMPLServer::kdRRTConnect::Motion;
    // here is about 1000 lines code
    // I am sure here works, because i have test it in main.cpp and that's really 
    // what i want. The logic are just get n random point, which are the around                      
    // small room of state (rstate in RRTConnect )-> build the KD Tree -> give a 
    // searchPoint to find the nearestNeighbor point in KDTree -> convert the
    // nearestNeighbor point in state -> make a new motion *nmotion -> save it i
    //in motion->state

    return motion;
}
protected:

    std::vector<_T> motions;
};

现在我给我完整的kdRRTConnect,与RRTConnect Planner一样快 RRTConnect.h(http://ompl.kavrakilab.org/RRTConnect_8h_source.html) RRTConnect.cpp(http://ompl.kavrakilab.org/RRTConnect_8cpp_source.html

在kdRRTConnect.h

namespace ob = ompl::base;
namespace og = ompl::geometric;

namespace PathPlannerOMPLServer
{
    class kdRRTConnect :public ompl::base::Planner
    {
    public:

        //brief constructor 
        kdRRTConnect(const ompl::base::SpaceInformationPtr &si);

        kdRRTConnect();

        virtual ~kdRRTConnect();

        virtual void getPlannerData(ompl::base::PlannerData &data)const;

        virtual ompl::base::PlannerStatus solve(const ompl::base::PlannerTerminationCondition &ptc);

        virtual void clear();

        void setRange(double distance)
        {
            maxDistance_ = distance;
        }

        double getRange() const
        {
            return maxDistance_;
        }

        template<template<typename T> class NN>
        void setNearestNeighbors()
        {
            tStart_.reset(new NN<Motion*>());
            tStart_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));

            tGoal_.reset(new NN<Motion*>());
            tGoal_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
        }

        virtual void setup();

        //define Motion same as RRTConnect, but in public
        class Motion
        {
        public:

            Motion() : root(nullptr), state(nullptr), parent(nullptr)
            {
                parent = nullptr;
                state = nullptr;
            }

            Motion(const ompl::base::SpaceInformationPtr &si) : root(nullptr), state(si->allocState()), parent(nullptr)
            {
            }

            ~Motion()
            {
            }

            const ompl::base::State *root;
            ompl::base::State       *state;
            Motion            *parent;

        };

    protected:

        // a Sub nearest-neighbor datastructure represents a tree of motions
        typedef std::shared_ptr< ompl::NearestNeighbors<Motion*>> TreeData;

        //brief Info. attached to gowing a tree motions(use internally)
        struct TreeGrowingInfo
        {
            ompl::base::State *xstate;
            Motion *xmotion;
            bool start;
        };

        //brief The state of the tree after an attempt to extend it 
        enum GrowState
        {
            /// no progress has been made
            TRAPPED,
            /// progress has been made towards the randomly sampled state
            ADVANCED,
            /// the randomly sampled state was reached, d !> maxDistance
            //double d = si_->distance(nmotion->state, rmotion->state); <- in growTree()
            REACHED
        };

        //brief Free the memory allocated by this planner 
        void freeMemory();

        double distance(const ob::State *p1, const ob::State *p2)
        {
            //define p1's and p2's StateType as SE3StateSpace

            const ob::SE3StateSpace::StateType* state3Dp1 = p1->as<ob::SE3StateSpace::StateType>();

            double x1 = state3Dp1->getX();
            double y1 = state3Dp1->getY();
            double z1 = state3Dp1->getZ();

            const ob::SE3StateSpace::StateType* state3Dp2 = p2->as<ob::SE3StateSpace::StateType>();

            double x2 = state3Dp2->getX();
            double y2 = state3Dp2->getY();
            double z2 = state3Dp2->getZ();

            double dx = x1 - x2;
            double dy = y1 - y2;
            double dz = z1 - z2;

            return sqrt(dx*dx + dy*dy + dz*dz);
        }

        double distanceFunction(const Motion *a, const Motion *b) const
        {
            ob::State *stateA = a->state;
            ob::State *stateB = b->state;

            ob::SE3StateSpace::StateType* stateTypeA = stateA->as<ob::SE3StateSpace::StateType>();
            ob::SE3StateSpace::StateType* stateTypeB = stateB->as<ob::SE3StateSpace::StateType>();

            double x1 = stateTypeA->getX();
            double y1 = stateTypeA->getY();
            double z1 = stateTypeA->getZ();

            double x2 = stateTypeB->getX();
            double y2 = stateTypeB->getY();
            double z2 = stateTypeB->getZ();

            double dx = x1 - x2;
            double dy = y1 - y2;
            double dz = z1 - z2;

            return sqrt(dx * dx + dy * dy + dz * dz);
        }

        void interpolate(const ob::State *from, const ob::State *to, const double t, ob::State *state) const
        {
            const ob::SE3StateSpace::StateType* s1 = from->as<ob::SE3StateSpace::StateType>();
            const ob::SE3StateSpace::StateType* s2 = to->as<ob::SE3StateSpace::StateType>();
            ob::SE3StateSpace::StateType* lastValid = state->as<ob::SE3StateSpace::StateType>();

            //Separate the path from s1 to s2 into nd Segment. nd = stateSpace_->validSegmentCount(s1, s2); in checkMotion and get the distance difference of X,Y,Z Value form s1 to s2 
            double distanceX = s2->getX() - s1->getX();
            double distanceY = s2->getY() - s1->getY();
            double distanceZ = s2->getZ() - s1->getZ();


            lastValid->setXYZ(s1->getX() + distanceX*t, s1->getY() + distanceY*t, s1->getZ() + distanceZ*t);

        }

        //brief Grow a tree towards a random state
        GrowState growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion);

        //brief State sampler
        ompl::base::StateSamplerPtr         sampler_;

        //brief The start tree
        TreeData                      tStart_;

        //brief The goal tree 
        TreeData                      tGoal_;

        //brief The maximum length of a motion to be added to a tree 
        double                        maxDistance_;

        //brief The random number generator
        ompl::RNG                           rng_;

        /** \brief The pair of states in each tree connected during planning.  Used for PlannerData computation */
        std::pair<ompl::base::State*, ompl::base::State*>      connectionPoint_;

    };
}

在kdRRTConnect.cpp

namespace ob = ompl::base;

PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(const ompl::base::SpaceInformationPtr &si) : ompl::base::Planner(si, "kdRRTConnect")
{
    specs_.recognizedGoal = ompl::base::GOAL_SAMPLEABLE_REGION;
    specs_.directed = true;

    maxDistance_ = 0.0;

    Planner::declareParam<double>("range", this, &kdRRTConnect::setRange, &kdRRTConnect::getRange, "0.:1.:10000.");
    connectionPoint_ = std::make_pair<ompl::base::State*, ompl::base::State*>(nullptr, nullptr);
}

PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
    :
    ompl::base::Planner((const ompl::base::SpaceInformationPtr &)*((ompl::base::SpaceInformationPtr*)(unsigned char*)0), "kdRRTConnect")
{
    //typedef std::shared_ptr <Motion> motion_ptr;
    typedef std::shared_ptr < ompl::NearestNeighbors<Motion*>> nn_ptr;

    nn_ptr nn_;

    nn_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}

PathPlannerOMPLServer::kdRRTConnect::~kdRRTConnect()
{
    freeMemory();
}

void PathPlannerOMPLServer::kdRRTConnect::setup()
{
    Planner::setup();
    ompl::tools::SelfConfig sc(si_, getName());
    sc.configurePlannerRange(maxDistance_);

    if (!tStart_)
        tStart_.reset(ompl::tools::SelfConfig::getDefaultNearestNeighbors<Motion*>(this));
    if (!tGoal_)
        tGoal_.reset(ompl::tools::SelfConfig::getDefaultNearestNeighbors<Motion*>(this));

    tStart_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
    tGoal_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}

void PathPlannerOMPLServer::kdRRTConnect::freeMemory()
{
    std::vector<Motion*> motions;

    if (tStart_)
    {
        tStart_->list(motions);
        for (unsigned int i = 0; i < motions.size(); ++i)
        {
            if (motions[i]->state)
                si_->freeState(motions[i]->state);
            delete motions[i];
        }
    }

    if (tGoal_)
    {
        tGoal_->list(motions);
        for (unsigned int i = 0; i < motions.size(); ++i)
        {
            if (motions[i]->state)
                si_->freeState(motions[i]->state);
            delete motions[i];
        }
    }
}

void PathPlannerOMPLServer::kdRRTConnect::clear()
{
    ompl::base::Planner::clear();
    sampler_.reset();
    freeMemory();
    if (tStart_)
        tStart_->clear();
    if (tGoal_)
        tGoal_->clear();
    connectionPoint_ = std::make_pair<ompl::base::State*, ompl::base::State*>(nullptr, nullptr);
}

PathPlannerOMPLServer::kdRRTConnect::GrowState PathPlannerOMPLServer::kdRRTConnect::growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion)
{
    /* find closest state in the tree */
    Motion *nmotion = tree->nearest(rmotion);

    /* assume we can reach the state we go towards */
    bool reach = true;

    /* find state to add */
    ompl::base::State *dstate = rmotion->state;
    double d = distance(nmotion->state, rmotion->state);
    if (d > maxDistance_)
    {
        //si_->getStateSpace()->interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
        interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
        dstate = tgi.xstate;
        reach = false;
    }
    // if we are in the start tree, we just check the motion like we normally do;
    // if we are in the goal tree, we need to check the motion in reverse, but checkMotion() assumes the first state it receives as argument is valid,
    // so we check that one first
    bool validMotion = tgi.start ? si_->checkMotion(nmotion->state, dstate) : si_->getStateValidityChecker()->isValid(dstate) && si_->checkMotion(dstate, nmotion->state);

    if (validMotion)
    {
        /* create a motion */
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, dstate);
        motion->parent = nmotion;
        motion->root = nmotion->root;
        tgi.xmotion = motion;

        tree->add(motion);
        if (reach)
            return REACHED;
        else
            return ADVANCED;
    }
    else
        return TRAPPED;
}

ompl::base::PlannerStatus PathPlannerOMPLServer::kdRRTConnect::solve(const ompl::base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    ompl::base::GoalSampleableRegion *goal = dynamic_cast<ompl::base::GoalSampleableRegion*>(pdef_->getGoal().get());

    if (!goal)
    {
        OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
        return ompl::base::PlannerStatus::UNRECOGNIZED_GOAL_TYPE;
    }

    while (const ompl::base::State *st = pis_.nextStart())
    {
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, st);
        motion->root = motion->state;
        tStart_->add(motion);
    }

    if (tStart_->size() == 0)
    {
        OMPL_ERROR("%s: Motion planning start tree could not be initialized!", getName().c_str());
        return ompl::base::PlannerStatus::INVALID_START;
    }

    if (!goal->couldSample())
    {
        OMPL_ERROR("%s: Insufficient states in sampleable goal region", getName().c_str());
        return ompl::base::PlannerStatus::INVALID_GOAL;
    }

    if (!sampler_)
        sampler_ = si_->allocStateSampler();

    OMPL_INFORM("%s: Starting planning with %d states already in datastructure", getName().c_str(), (int)(tStart_->size() + tGoal_->size()));

    TreeGrowingInfo tgi;
    tgi.xstate = si_->allocState();

    Motion   *rmotion = new Motion(si_);
    ompl::base::State *rstate = rmotion->state;
    bool startTree = true;
    bool solved = false;

    while (ptc == false)
    {
        TreeData &tree = startTree ? tStart_ : tGoal_;
        tgi.start = startTree;
        startTree = !startTree;
        TreeData &otherTree = startTree ? tStart_ : tGoal_;

        if (tGoal_->size() == 0 || pis_.getSampledGoalsCount() < tGoal_->size() / 2)
        {
            const ompl::base::State *st = tGoal_->size() == 0 ? pis_.nextGoal(ptc) : pis_.nextGoal();
            if (st)
            {
                Motion *motion = new Motion(si_);
                si_->copyState(motion->state, st);
                motion->root = motion->state;
                tGoal_->add(motion);
            }

            if (tGoal_->size() == 0)
            {
                OMPL_ERROR("%s: Unable to sample any valid states for goal tree", getName().c_str());
                break;
            }
        }

        /* sample random state */
        sampler_->sampleUniform(rstate);

        GrowState gs = growTree(tree, tgi, rmotion);

        if (gs != TRAPPED)
        {
            /* remember which motion was just added */
            Motion *addedMotion = tgi.xmotion;

            /* attempt to connect trees */

            /* if reached, it means we used rstate directly, no need top copy again */
            if (gs != REACHED)
                si_->copyState(rstate, tgi.xstate);

            GrowState gsc = ADVANCED;
            tgi.start = startTree;
            while (gsc == ADVANCED)
                gsc = growTree(otherTree, tgi, rmotion);

            Motion *startMotion = startTree ? tgi.xmotion : addedMotion;
            Motion *goalMotion = startTree ? addedMotion : tgi.xmotion;

            /* if we connected the trees in a valid way (start and goal pair is valid)*/
            if (gsc == REACHED && goal->isStartGoalPairValid(startMotion->root, goalMotion->root))
            {
                // it must be the case that either the start tree or the goal tree has made some progress
                // so one of the parents is not nullptr. We go one step 'back' to avoid having a duplicate state
                // on the solution path
                if (startMotion->parent)
                    startMotion = startMotion->parent;
                else
                    goalMotion = goalMotion->parent;

                connectionPoint_ = std::make_pair(startMotion->state, goalMotion->state);

                /* construct the solution path */
                Motion *solution = startMotion;
                std::vector<Motion*> mpath1;
                while (solution != nullptr)
                {
                    mpath1.push_back(solution);
                    solution = solution->parent;
                }

                solution = goalMotion;
                std::vector<Motion*> mpath2;
                while (solution != nullptr)
                {
                    mpath2.push_back(solution);
                    solution = solution->parent;
                }

                ompl::geometric::PathGeometric *path = new ompl::geometric::PathGeometric(si_);
                path->getStates().reserve(mpath1.size() + mpath2.size());
                for (int i = mpath1.size() - 1; i >= 0; --i)
                    path->append(mpath1[i]->state);
                for (unsigned int i = 0; i < mpath2.size(); ++i)
                    path->append(mpath2[i]->state);

                pdef_->addSolutionPath(ompl::base::PathPtr(path), false, 0.0, getName());
                solved = true;
                break;
            }
        }
    }

    si_->freeState(tgi.xstate);
    si_->freeState(rstate);
    delete rmotion;

    OMPL_INFORM("%s: Created %u states (%u start + %u goal)", getName().c_str(), tStart_->size() + tGoal_->size(), tStart_->size(), tGoal_->size());

    return solved ? ompl::base::PlannerStatus::EXACT_SOLUTION : ompl::base::PlannerStatus::TIMEOUT;
}

void PathPlannerOMPLServer::kdRRTConnect::getPlannerData(ompl::base::PlannerData &data) const
{
    Planner::getPlannerData(data);

    std::vector<Motion*> motions;
    if (tStart_)
        tStart_->list(motions);

    for (unsigned int i = 0; i < motions.size(); ++i)
    {
        if (motions[i]->parent == nullptr)
            data.addStartVertex(ompl::base::PlannerDataVertex(motions[i]->state, 1));
        else
        {
            data.addEdge(ompl::base::PlannerDataVertex(motions[i]->parent->state, 1),
                ompl::base::PlannerDataVertex(motions[i]->state, 1));
        }
    }

    motions.clear();
    if (tGoal_)
        tGoal_->list(motions);

    for (unsigned int i = 0; i < motions.size(); ++i)
    {
        if (motions[i]->parent == nullptr)
            data.addGoalVertex(ompl::base::PlannerDataVertex(motions[i]->state, 2));
        else
        {
            // The edges in the goal tree are reversed to be consistent with start tree
            data.addEdge(ompl::base::PlannerDataVertex(motions[i]->state, 2),
                ompl::base::PlannerDataVertex(motions[i]->parent->state, 2));
        }
    }

    // Add the edge connecting the two trees
    data.addEdge(data.vertexIndex(connectionPoint_.first), data.vertexIndex(connectionPoint_.second));
}

在这里,我清除了PathPathnerOMPLServer程序的结构,它有四个成员:SubNearestNeighbors,kdRRTConnect,这些函数是我自己编写的near(),isValid(),checkMotion(),interpolate()函数。这四个功能分别独立运行,但是现在我必须让它们与我的Planner kdRRTConnect一起使用。其他两个成员CollisionCheck和MotionValidator与该问题无关。 SubsNearestNeighbor继承OMPL源文件Ompl :: NearestNeighbors <_T>,而kdRRTConnect继承OMPL源文件Ompl :: base :: Planner。在Visual C ++中,所有源文件都构建了一个OMPL库,而我的程序PathPlannerOMPLServer则使用它。在这里我画一幅画来简化我之前所说的内容。Relation between my Program PathPlannerOMPLServer, OMPL Source File and Ompl lib

顺便说一句,我在ompl论坛中曾问过同样的问题,但管理员说这不是错误,请将我的问题设置为无效,不再回答。 这是我问的链接问题#436:https://bitbucket.org/ompl/ompl/issues/436/about-template-after-inheriting-ompl

抱歉,我无法简化示例。

非常感谢,我希望有人能给我更多的小费。

eoeo