Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

This is causing some of my C++ students a major headache ...

349 views
Skip to first unread message

Bob Langelaan

unread,
Mar 23, 2016, 2:37:03 PM3/23/16
to
My students are normally able to figure out on their own any issues that arise while doing their assignments. But I had 3 different students run into this issue this semester and end up having to reach out to me for help. I believe that this is mostly caused by their inability to map the error message to their solution.

Here is a very simplified version of the issue:

class myClass
{
const int i;
};

int main()
{
myClass a, b;
a = b;
}

The code above generates 3 errors in MS VS 2015, all of which refer to "attempting to reference a deleted function".

I must admit it took me a while to find the issue the first time. Realize that the code the student sent me was much more involved than the example above.

Of course it can be argued that it is very rare (never?) that you would actually want to define and initialize a non-const data member in a class interface file. But these are students just learning the language and relatively new to object oriented programming as well and as such are more likely to make to make such a logic error (not defining a const member as static).

My point is that students would be more likely to able to figure the issue on their own if the MS VS 2015 error messages were more illuminating.


Bob Langelaan

unread,
Mar 23, 2016, 2:42:35 PM3/23/16
to
There was an error in my original post. I meant to say (corrected part in CAPS):

Of course it can be argued that it is very rare (never?) that you would actually want to define and initialize a CONST DATA MEMBER WHICH IS NOT STATIC in a class interface file. But these are students just learning the language and relatively new to object oriented programming as well and as such are more likely to make to make such a logic error (not defining a const member as static).

Ian Collins

unread,
Mar 23, 2016, 3:28:41 PM3/23/16
to
On 03/24/16 07:36, Bob Langelaan wrote:
> My students are normally able to figure out on their own any issues
> that arise while doing their assignments. But I had 3 different
> students run into this issue this semester and end up having to reach
> out to me for help. I believe that this is mostly caused by their
> inability to map the error message to their solution.
>
> Here is a very simplified version of the issue:
>
> class myClass
> {
> const int i;
> };
>
> int main()
> {
> myClass a, b;
> a = b;
> }
>
> The code above generates 3 errors in MS VS 2015, all of which refer
> to
"attempting to reference a deleted function".

Firstly, please wrap your lines!

Second try using an alternative compiler. The two I use make the cause
much clearer:

CC -std=c++14 ~/temp/c.cc
"/home/ian/temp/c.cc", line 8: Error: a must be initialized.
"/home/ian/temp/c.cc", line 8: Error: Constant members of 'myClass' must
be initialized.
"/home/ian/temp/c.cc", line 8: Error: b must be initialized.
"/home/ian/temp/c.cc", line 8: Error: Constant members of 'myClass' must
be initialized.
"/home/ian/temp/c.cc", line 9: Error: Using deleted function
'myClass::operator=(const myClass&)'.

and:

g++ -std=c++14 ~/temp/c.cc
/home/ian/temp/c.cc: In function ‘int main()’:
/home/ian/temp/c.cc:8:10: error: use of deleted function
‘myClass::myClass()’
myClass a, b;
^
/home/ian/temp/c.cc:1:7: note: ‘myClass::myClass()’ is implicitly
deleted because the default definition would be ill-formed:
class myClass
^
/home/ian/temp/c.cc:1:7: error: uninitialized const member in ‘class
myClass’
/home/ian/temp/c.cc:3:12: note: ‘const int myClass::i’ should be initialized
const int i;
^
/home/ian/temp/c.cc:8:13: error: use of deleted function
‘myClass::myClass()’
myClass a, b;
^
/home/ian/temp/c.cc:9:4: error: use of deleted function ‘myClass&
myClass::operator=(const myClass&)’
a = b;
^
/home/ian/temp/c.cc:1:7: note: ‘myClass& myClass::operator=(const
myClass&)’ is implicitly deleted because the default definition would be
ill-formed:
class myClass
^
/home/ian/temp/c.cc:1:7: error: non-static const member ‘const int
myClass::i’, can’t use default assignment operator

--
Ian Collins

Vir Campestris

unread,
Mar 24, 2016, 7:03:28 PM3/24/16
to
On 23/03/2016 19:28, Ian Collins wrote:
> Second try using an alternative compiler. The two I use make the cause
> much clearer:

The trouble is that while Clang (and, in competition, GCC) have spent a
lot of time and trouble making sensible error messages, and Microsoft
have not, I am not yet aware of an IDE for them which is any where near
as good as the Microsoft one.

That may be an issue for his students.

Andy

Robbie Hatley

unread,
Mar 24, 2016, 8:26:09 PM3/24/16
to

On 3/23/2016 11:36 AM, Bob Langelaan wrote:

> class myClass
> {
> const int i;
> };
>
> int main()
> {
> myClass a, b;
> a = b;
> }
>
> The code above generates 3 errors in MS VS 2015, all of which
> refer to "attempting to reference a deleted function"....
> ... it took me a while to find the issue the first time....
> ... students would be more likely to able to figure the issue
> on their own if the MS VS 2015 error messages were more
> illuminating.

This is yet another case where I find MS software bloody annoying.
Try Gnu's g++. While it is annoyingly silent about *some* errors
(see my post below about "initializing std::string to 0"),
it prints *lots* of warnings and errors for your code, including
a warning to the effect that "warning: non-static const member
‘const int myClass::i’ in class without a constructor":

%make const-member-test.exe DEBUG=1 PEDANTIC=1
Using pattern rule %.exe:%.cpp to compile const-member-test.cpp to const-member-test.exe:
g++ -I /rhe/include -pedantic -Wall -Wextra -Wfloat-equal -Wshadow -Wcast-qual
-Wcast-align -Wconversion -Winline -Wcomments -Wundef -Wunused-macros
-Wold-style-cast -Woverloaded-virtual -std=gnu++14 const-member-test.cpp
-L/rhe/lib -L/lib -lrh -lfl -ly -lm -lname -o /rhe/bin/test/const-member-test.exe

const-member-test.cpp:3:12: warning: non-static const member ‘const int myClass::i’
in class without a constructor [-Wuninitialized]
const int i;
^
const-member-test.cpp: In function ‘int main()’:
const-member-test.cpp:8:10: error: use of deleted function ‘myClass::myClass()’
myClass a, b;
^
const-member-test.cpp:1:7: note: ‘myClass::myClass()’ is implicitly deleted because
the default definition would be ill-formed:
class myClass
^
const-member-test.cpp:1:7: error: uninitialized const member in ‘class myClass’
const-member-test.cpp:3:12: note: ‘const int myClass::i’ should be initialized
const int i;
^
const-member-test.cpp:8:13: error: use of deleted function ‘myClass::myClass()’
myClass a, b;
^
const-member-test.cpp:9:4: error: use of deleted function
‘myClass& myClass::operator=(const myClass&)’
a = b;
^
const-member-test.cpp:1:7: note: ‘myClass& myClass::operator=(const myClass&)’
is implicitly deleted because the default definition would be ill-formed:
class myClass
^
const-member-test.cpp:1:7: error: non-static const member ‘const int myClass::i’,
can’t use default assignment operator

/rhe/maketail:198: recipe for target 'const-member-test.exe' failed
make: [const-member-test.exe] Error 1




--
Cheers,
Robbie Hatley
Midway City, CA, USA
perl -le 'print "\154o\156e\167o\154f\100w\145ll\56c\157m"'
http://www.well.com/user/lonewolf/
https://www.facebook.com/robbie.hatley

Robbie Hatley

unread,
Mar 24, 2016, 8:42:26 PM3/24/16
to

Btw, there is nothing inherently wrong with having a non-static
(per-object) const member in a class. But if you *do*, you must
provide an assignment operator, even if it does nothing.

The following correction of your code compiles and runs fine:

#include <iostream>
using std::cout; using std::endl;
class myClass
{
public:
operator= (myClass) {return 0;}
const int i = 17;
};

int main()
{
myClass a;
myClass b;
a = b;
cout << "a.i = " << a.i << endl;
cout << "b.i = " << b.i << endl;
}

OUTPUT:

%const-member-test.exe
a.i = 17
b.i = 17

Ian Collins

unread,
Mar 24, 2016, 9:01:09 PM3/24/16
to
On 03/25/16 13:42, Robbie Hatley wrote:
>
> Btw, there is nothing inherently wrong with having a non-static
> (per-object) const member in a class. But if you *do*, you must
> provide an assignment operator, even if it does nothing.

If the const has an initialiser, why wouldn't you make it static?

> The following correction of your code compiles and runs fine:
>
> #include <iostream>
> using std::cout; using std::endl;
> class myClass
> {
> public:
> operator= (myClass) {return 0;}

That's a syntax error...

--
Ian Collins

Robbie Hatley

unread,
Mar 24, 2016, 9:50:21 PM3/24/16
to

Oh, and I should also add that your assignment operator *need not*
do nothing. It's free to copy-over the non-const parts of objects
of your class.

For example:

#include <iostream>
using std::cout; using std::endl;
class myClass
{
public:
myClass() : i(42), j(13) {}
myClass(int a, int b) : i(a), j(b) {}
myClass& operator= (myClass o) {this->j = o.j; return *this;}
geti() {return i;}
getj() {return j;}
private:
int const i;
int j;
};

int main()
{
myClass a;
myClass b (86, 74);
cout << "Before assigning b = a :" << endl;
cout << "a.i = " << a.geti() << endl;
cout << "a.j = " << a.getj() << endl;
cout << "b.i = " << b.geti() << endl;
cout << "b.j = " << b.getj() << endl;
b = a;
cout << "After assigning b = a :" << endl;
cout << "a.i = " << a.geti() << endl;
cout << "a.j = " << a.getj() << endl;
cout << "b.i = " << b.geti() << endl;
cout << "b.j = " << b.getj() << endl;
}


OUTPUT:

%const-member-test.exe
Before assigning b = a :
a.i = 42
a.j = 13
b.i = 86
b.j = 74
After assigning b = a :
a.i = 42
a.j = 13
b.i = 86
b.j = 13


Note that b.j has now changed from 74 to 13, because j is a
non-const member, so the = operator can copy it over.
0 new messages