-3

in the following code:

class prova: public std::map< int,int >
{
 public:
 prova():a(5){}
 int a;

};

int main()
{
 std::vector<prova> p;
 prova obj;
 p.push_back(obj); 
 return 0;
}

it works without problem; If I add a reference member

class prova: public std::map< int,int >
{
 public:
 prova():a(5){}
 int a;
 int& b=a;
};

int main()
{
 std::vector<prova> p;
 prova obj;
 p.push_back(obj); 
 return 0;
}

I have

warning: non-static data member initializers only     available with -std=c++11 or -std=gnu++11 [enabled by default]|
/home/andrea/Scaricati/prova.cpp||In instantiation of ‘void 
std::vector<_Tp,_Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) 
[with _Tp = prova; _Alloc = std::allocator<prova>; 
std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<prova*, std::vector<prova> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = prova*]’:|
/usr/include/c++/4.8/bits/stl_vector.h|913|required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = prova; _Alloc = std::allocator<prova>;   std::vector<_Tp, _Alloc>::value_type = prova]’|
/home/andrea/Scaricati/prova.cpp|19|required from here|
/home/andrea/Scaricati/prova.cpp|4|error: non-static reference member ‘int& prova::b’,     can’t use default assignment operator|
/usr/include/c++/4.8/bits/vector.tcc|335|note: synthesized method ‘prova&     prova::operator=(const prova&)’ first required here     
|||=== Build failed: 1 error(s), 4 warning(s) (0 minute(s), 0 second(s)) ===|

no problems adding -std=g++11 like suggested from warning. If I remove the vector declaration I have just the warning without the error. Why C++ old standard can't do it? what is the problem with references attributes? is there a system to do same things without using c++11 standard? I try

class prova: public std::map< int,int >
{
 public:
 prova():a(5),b(a){}
 int a;
 int &b;
};

but I get errors. Why this? thanks!

volperossa
  • 1,339
  • 20
  • 33
  • 4
    non-static data member initializers is a C++11 feature. Anyway if you maintain self-references you need to write the copy ctor and assignment operator yourself or things will get messy. – T.C. Oct 03 '14 at 21:38
  • "Why C++ old standard can't do it?": as stated in the warning, "non-static data member initializers only available with -std=c++11 or -std=gnu++11". Honestly, I'm not sure why it's not an error - I don't know what the compiler in pre-C++11 mode does with the non-static member initializer. – Michael Burr Oct 03 '14 at 21:43
  • Also, inheriting from a standard template library is a bit frowned upon http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4143/Working-with-the-Final-Class-in-C.htm and http://stackoverflow.com/questions/922248/is-there-any-real-risk-to-deriving-from-the-c-stl-containers – AndyG Oct 03 '14 at 21:52
  • ok..but why error on the iterator?! – volperossa Oct 03 '14 at 21:55
  • 1
    @volperossa: because `push_back()` from an lvalue needs to copy the element and as the error states (granted - it's buried in a bunch of noise; that's still a big problem with C++ template errors): "error: non-static reference member `'int& prova::b'`, can’t use default assignment operator". So, as T.C. mentioned, you'll need to define your own copy operations in order to correctly handle the reference. – Michael Burr Oct 03 '14 at 23:11

1 Answers1

2

You get a warning because your compiler is smart enough to know the syntax of C++11. In C++ such syntax int& b= a is called an In-class member initializer and in previous standards, this could only be done with static const variables. C++11 relaxes those constraints.

From Stroustrup's page:

In C++98, only static const members of integral types can be initialized in-class, and the initializer has to be a constant expression. These restrictions ensure that we can do the initialization at compile-time.

For example:

int var = 7;

class X {       
    static const int m1 = 7;        // ok       
    const int m2 = 7;               // error: not static        
    static int m3 = 7;              // error: not const         
    static const int m4 = var;      // error: initializer not constant expression 
    static const string m5 = "odd"; // error: not integral type         
    // ...  
}; 

The basic idea for C++11 is to allow a non-static data member to be initialized where it is declared (in its class). A constructor can then use the initializer when run-time initialization is needed. Consider:

class A {   
public: 
    int a = 7;  
};

This is equivalent to:

class A {   
public:         
    int a;      
    A() : a(7) {}   
};
AndyG
  • 39,700
  • 8
  • 109
  • 143
  • The two `A`'s are not strictly equivalent in C++14. The first is an aggregate; the second one isn't. – T.C. Oct 03 '14 at 21:47
  • Thanks, I didn't know that. I removed any mention of C++14 in my post. – AndyG Oct 03 '14 at 21:49
  • ok but with this class prova: public std::map< int,int > { public: prova():a(5),b(a){} int a; int &b; }; i get error – volperossa Oct 03 '14 at 21:50
  • error: non-static reference member ‘int& prova::b’, can’t use default assignment operator| – volperossa Oct 03 '14 at 21:51
  • @volperossa: Not sure, could be your compiler. Works for me in VS2013. (I removed the inheritance from std::map, but that shouldn't matter) – AndyG Oct 03 '14 at 22:03