0

I am working on genetically evolved neural networks. I wrote a program using visual studio 2005 in 2008. Now I converted the program into Eclipse(Linux) and VS 2013(Win) projects with c++11 support. After running, both projects gave same error:

taking address of temporary [-fpermissive]

After searching a lot I found this error arises as new C++ standards doesn't allow to take address of a temporary object. As all objects are created using "new" (so I guess they should remain available all the time). I figured out the problem partially but don't know how to solve it. If you run the eclipse project it will highlight just two errors in the project.

As its hard to explain in words as it need full code to examine so I have hosted eclipse project on git at https://bitbucket.org/a-akram/geans.git which I made accessible to everyone.

Main problem is with variables wp1 & wp2. m_vPopulatin is a vector containing addresses of neural networks.

CNeuralNetwork* CGeneticEngine::Evolve()
{
    CLearningEngine *l;
    double totalError =  0.0;
    for (int iter = 0;iter < CGN_MAXITER; iter++)
    {
        for (int i = 0;i < CGN_POPULATION; i++)
        {
            l = new CLearningEngine(m_vPopulation[i]);
            l->Run(m_vTrainingDataset);
            for(unsigned int p = 0; p < m_vTrainingDataset->size(); p++)
            {
                totalError = totalError + m_vPopulation[i]->getm_dTotalNetworkError();
                totalError = totalError/m_vTrainingDataset->size();
            }
            if (totalError < CGN_THRESHOLD)
                 return m_vPopulation[i];

            m_dErrors[i] = totalError;
        }
        SortFitnesses();
        NewPopulation();
    }
    return NULL;

}

void CGeneticEngine::NewPopulation()
{
    int id1, id2;
    double temp;
    std::vector <CSynapticConnection *> *wp1;
    std::vector <CSynapticConnection *> *wp2;
    for (int i=0;i<CGN_POPULATION / 2;i++)
    {
        id1 = rand() % CGN_POPULATION / 2;
        id2 = rand() % CGN_POPULATION / 2 + CGN_POPULATION / 2;

        wp1 = &m_vPopulation[id1]->getm_vListofSynaptics();
        wp2 = &m_vPopulation[id2]->getm_vListofSynaptics();

        // Cross over the weights.
        for (int j = 0; j < 2; j++)
        {
            temp = (*wp1)[j+6]->getWeight();
            (*wp1)[j+6]->setWeight((*wp2)[j+6]->getWeight() );
            (*wp2)[j+6]->setWeight(temp);
        }

        //  adding slight genetic change due to crossover randomly.
        if (rand() % 10 < 2)
        {
            for(unsigned int j = 0; j < wp1->size();j++)
                (*wp1)[j]->changeWeight((double)(rand())/(32767/2) - 1);

            for(unsigned int j = 0; j < wp2->size();j++)
                (*wp2)[j]->changeWeight((double)(rand())/(32767/2) - 1);
         }
    }
}

As this is my first question on this forum so I might not phrased well so I request moderators not to close it at the moment. I will make it more clear if necessary. But with the project files in hand it will be very easy for you guys to figure out the problem and solution.

I will highly appreciate your help to resolve the issue... please let me know if you need any further information.

manlio
  • 18,345
  • 14
  • 76
  • 126
Adeel
  • 343
  • 1
  • 2
  • 7
  • _"C++ standards doesn't allow to take address of a temporary object"_ You mean an object on the stack? You can take the address of those; they just won't be valid after the function returns. Also, no one is going to clone your project; please include a [MCVE](http://stackoverflow.com/help/mcve) in the question itself. – Colonel Thirty Two Mar 08 '15 at 15:54
  • Where do you delete `l`? Use smart pointers. – Neil Kirk Mar 09 '15 at 14:27
  • @Neil Kirk: Thanks for highlighting smart pointers. I will use smart pointers...as this is an old code which I am modifying to current C++11 standard... – Adeel Mar 09 '15 at 14:51

1 Answers1

2

First consider this subset of the CNeuralNetwork class:

class CNeuralNetwork
{
  // ...
public:
  std::vector<CSynapticConnection *> getm_vListofSynaptics()
  {
    return m_vListofSynaptics;
  }

  std::vector<CSynapticConnection*> m_vListofSynaptics;
  // ...
};

Here you have a getter (getm_vListofSynaptics()) that returns a temporary value: a copy of the public data member m_vListofSynaptics.

In the CGeneticEngine::NewPopulation() function you're taking the address of the temporary object and this triggers the error:

wp1 = &m_vPopulation[id1]->getm_vListofSynaptics();
wp2 = &m_vPopulation[id2]->getm_vListofSynaptics();

(see Why is taking the address of a temporary illegal? for further details).

There are some changes you have to consider/apply:

  • getters/setters are useful (?) for encapsulation of behaviour / hiding the internal representation of a property but m_vListofSynaptics is public so the getter "buys you next to nothing" (e.g. see Why use getters and setters? / Public Data members vs Getters, Setters for some insight)

  • about the error, you could (this is only a "quick-fix", the design can seemingly be changed to completely avoid the getter):

    • change the getter so that it returns a reference / pointer to the data member (data member should be private)

      class CNeuralNetwork
      {
      // ...
      public:
        std::vector<CSynapticConnection *> *getm_vListofSynaptics()
        {
          return &m_vListofSynaptics;
        }
      private:
        std::vector<CSynapticConnection*> m_vListofSynaptics;
      };
      
    • directly access the m_vListofSynaptics data member (probably not a good idea):

      wp1 = &m_vPopulation[id1]->m_vListofSynaptics;
      

      (take a look at If a variable has getter and setter, should it be public?)

Community
  • 1
  • 1
manlio
  • 18,345
  • 14
  • 76
  • 126
  • thank you so much, it solved my problem. I prefer your first solution using getter function. but there is another error arrived. Its with GetID() which is implemented in main.cpp. How I can make it available for all classes e.g. in CLayer. Its not an issue with single file coding, but as I have classes in multiple files so I need this function accessible to them. Should I make it global (but I don't know how). – Adeel Mar 09 '15 at 13:45
  • You can take a look at [How do you define a global function in C++?](http://stackoverflow.com/questions/6874346/how-do-you-define-a-global-function-in-c) – manlio Mar 09 '15 at 15:04
  • ...or add a `static` counter directly to the `CNeuron` / `CLayer` / `CSynapticConnection` classes (with the corresponding `get()` method). – manlio Mar 09 '15 at 15:09