C/C++ Compiler error do to too much "constness" in my C++ program?

AI Thread Summary
The discussion centers on a C++ compilation error related to excessive use of "const" in the user's code, which is causing issues with the Rule of Three. The user is advised that defining a destructor without corresponding copy constructor and copy assignment operator leads to compilation failures, particularly when using iterators. It is noted that the code is not compliant with C++98/03 standards due to inconsistent use of data structures and unnecessary default constructors. The conversation also highlights the importance of understanding the implications of using "const" in relation to data structures like maps and sets. The user plans to revise their code to address these issues and adhere to the Rule of Three.
Jamin2112
Messages
973
Reaction score
12
Can someone try compiler this and tell me what error you get and what it means? https://github.com/jamkin/CSS-Template-Generator/tree/master/CSS%20Template%20Generator

I get
Mod note: Removed the [ I ] tags and the [ color ] BBCode tags, and replaced with [ code ] tags. There were too many emoticons to be able to read the error messages. The error messages are now readable, but some characters seem to have been removed.
Code:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:614:15: In instantiation of member function 'std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> >::eek:perator=' requested here
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__tree:1223:35: In instantiation of member function 'std::__1::__value_type<const std::__1::basic_string<char>, std::__1::basic_string<char> >::eek:perator=' requested here
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:941:21: In instantiation of function template specialization 'std::__1::__tree<std::__1::__value_type<const std::__1::basic_string<char>, std::__1::basic_string<char> >, std::__1::__map_value_compare<const std::__1::basic_string<char>, std::__1::__value_type<const std::__1::basic_string<char>, std::__1::basic_string<char> >, std::__1::less<const std::__1::basic_string<char> >, true>, std::__1::allocator<std::__1::__value_type<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >::__assign_unique<const std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > *>' requested here
/Users/me/Documents/CSS Template Generator/CSS Template Generator/ProgramDriver.cpp:35:20: In instantiation of member function 'std::__1::map<const std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::less<const std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, std::__1::basic_string<char> > > >::eek:perator=' requested here
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:1330:19: Candidate function not viable: 'this' argument has type 'const std::__1::basic_string<char>', but method is not marked const
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:1333:19: Candidate function not viable: 'this' argument has type 'const std::__1::basic_string<char>', but method is not marked const
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:1337:45: Candidate function not viable: 'this' argument has type 'const std::__1::basic_string<char>', but method is not marked const
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:1338:19: Candidate function not viable: 'this' argument has type 'const std::__1::basic_string<char>', but method is not marked const
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:1341:19: Candidate function not viable: 'this' argument has type 'const std::__1::basic_string<char>', but method is not marked const
and it's pointing to the following chunk in the <utility> file.

Code:
   _LIBCPP_INLINE_VISIBILITY

    pair&

    operator=(pair&& __p) _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&

                                    is_nothrow_move_assignable<second_type>::value)

    {

        first = _VSTD::forward<first_type>(__p.first); // <-------------- This line

        second = _VSTD::forward<second_type>(__p.second);

        return *this;

    }

I asked on Stack Overflow and someone said I was using too much const in my program.
 
Last edited by a moderator:
Technology news on Phys.org
You are violating the Rule of Three. You have defined a destructor for many of your classes. The rule of three suggests that you should also be defining a copy constructor and copy assignment operator.

An even bigger problem, at least with regard to compilation, is that you are defining a default constructor for many of your classes. Once you do this, the compiler cannot and must not define a copy constructor or copy assignment operator for you. You must write your own copy constructor and/or copy assignment operator if you want to have a custom default constructor and if you want make copies. You are making copies via your use of iterators, so your code fails.
 
It looks like the C++ compiler is recursing through the operator definition with no end in sight and so fails compilation after getting too deep.

Kind of like defining factorial as:

Code:
int factorial(int n) {
    if (n<1) return 1;
    return n*factorial(n);      // NOTICE: should be factorial(n-1) not factorial(n)
}

Running this code you'd get: factorial(5) -- > 5*5*5*...*factorial(5)...

So check your operator definition and see if that maybe you are doing the same kind of thing ie defining it in terms of itself.
 
D H said:
You are violating the Rule of Three. You have defined a destructor for many of your classes. The rule of three suggests that you should also be defining a copy constructor and copy assignment operator.

An even bigger problem, at least with regard to compilation, is that you are defining a default constructor for many of your classes. Once you do this, the compiler cannot and must not define a copy constructor or copy assignment operator for you. You must write your own copy constructor and/or copy assignment operator if you want to have a custom default constructor and if you want make copies. You are making copies via your use of iterators, so your code fails.

Thank you for your answer. Since 2 of my 3 destructors are trivial, would not defining them reduce the problems at hand?
 
Upon looking at your code in more detail, this is what I see:
  • It's not C++98/03-complaint. You are using (trying to use) braced initialization, something C++98/03 doesn't do all that well. I thought you wanted to learn C++98/03 first!
  • Your code is inconsistent. You are using a set of strings in one place, a vector of strings in another. That mixing and matching will never work.
  • You have too many default constructors and destructors that would best be left undefined (C++98/03) or declared as default (C++11).
  • As noted in the opening post, you are putting too much const into your code.
The last item could perhaps be viewed as a bug in the language. There's no way to change the key in a map or a set. The language makes sure you can't. (A user of a map or set could destroy the integrity of the container if this was allowed. So it isn't allowed.) There's no reason to make the key const because it essentially is const whether or not you declare it as such. Even though the distinction doesn't matter, the language unfortunately does distinguish between std :: set <std :: string > and std :: set < const std :: string >. This is a distinction that shouldn't matter, but it does. This is part of what is getting you in trouble.
 
The absence of brace initialization is the 1 thing I know C++11 has that I think C++98 should have (since it has brace initialization for structs, and since it's an extraneous amount of code to initialize vecs/sets/etc. otherwise).

The reason I have a set of strings is because that's an instance in which I don't need any repeated elements.

I must've totally misunderstood the "spirit" of C++, because I thought the idea was to always use const when a variable is intended to never change. At least from the book I read (C++ Primer Plus, 6th Edition) I got the impression that whenever you need a variable, you ask yourself

  • Is this variable ever going to change?
  • Is its address ever going to change?
  • If it's a parameter to a function, do I want to bring in the actual variable or a copy of it?
  • Etc.
I've heard Bjarne Stroustrup say we do all this fancy stuff to "help the compiler."

Anyways, if I have time today then I'll go back and rid my code of the constness and follow the Rule of 3.
 
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...

Similar threads

Replies
6
Views
2K
Replies
4
Views
4K
Replies
2
Views
2K
Replies
3
Views
3K
Replies
16
Views
4K
Replies
6
Views
3K
Replies
1
Views
3K
Replies
1
Views
2K
Replies
3
Views
3K
Back
Top