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

Click For Summary

Discussion Overview

The discussion revolves around a compiler error encountered in a C++ program, specifically related to the use of "const" qualifiers and the implications of the Rule of Three in class design. Participants explore the nature of the error messages and the potential causes related to constructors and assignment operators.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant requests help with a compiler error and shares specific error messages related to the use of "const" in their code.
  • Another participant points out a violation of the Rule of Three, suggesting that the user should define a copy constructor and copy assignment operator alongside the destructor.
  • A different participant compares the compilation issue to a recursive function error, suggesting that the operator definition might be improperly defined in terms of itself.
  • Some participants note that the code is not compliant with C++98/03 standards and highlight inconsistencies in the use of data structures like strings and vectors.
  • Concerns are raised about the excessive use of default constructors and destructors, with suggestions that some could be left undefined or declared as default in C++11.
  • One participant argues that the constness of keys in maps and sets is problematic, as it prevents changing keys and complicates the code unnecessarily.
  • A participant expresses confusion about the use of const, believing it should always be applied to variables intended to remain unchanged.

Areas of Agreement / Disagreement

Participants express multiple competing views regarding the use of const qualifiers, the Rule of Three, and the implications of C++ standards. The discussion remains unresolved with no consensus on the best approach to address the compiler error.

Contextual Notes

There are limitations regarding the assumptions made about C++ standards and the implications of using const in various contexts. The discussion also highlights unresolved issues related to the specific implementation of constructors and destructors in the user's code.

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.
 

Similar threads

  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 4 ·
Replies
4
Views
4K
Replies
5
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 3 ·
Replies
3
Views
3K
  • · Replies 16 ·
Replies
16
Views
5K
  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 3 ·
Replies
3
Views
3K