1

I just deleted a question that had set for 4 hours unanswered. I have mostly been able to answer it for myself through some trial and error and seem to have a good handle on it except for one piece. Why cant I declare my map as a const or was I doing it wrong? Complete example is at the bottom.

in class header

const std::map <char, char> UppercaseConvert;

in class constructor

const UppercaseConvert = { { 'A','a' },{ 'B','b' },{ 'C','c' },{ 'D','d' },{ 'E','e' },{ 'F','f' },
                     { 'G','g' },{ 'H','h' },{ 'I','i' },{ 'J','j' },{ 'K','k' },{ 'L','l' },
                     { 'M','m' },{ 'N','n' },{ 'O','o' },{ 'P','p' },{ 'Q','q' },{ 'R','r' },
                     { 'S','s' },{ 'T','t' },{ 'U','u' },{ 'V','v' },{ 'W','w' },{ 'X','x' },
                     { 'Y','y' },{ 'Z','z' } };

It will compile and work if I remove the const from both declaration and definition so it's not the end of the world. But, since this should be static shouldn't it have the const type?

This is the function it is used in:

std::string BCLogic::ConvertToLowerCase(FString word) {
   std::string ConvertedString;
   for (char character : word) {
     if (UppercaseConvert[character]) {
         ConvertedString.push_back(UppercaseConvert[character]);
     }
     else ConvertedString.push_back(character);
     }
return ConvertedString;
}

Edit: Complete Example that will not compile unless you remove const:

#include <iostream>
#include <string>
#include <map>


class Converter {

public:
    Converter();
    std::string ConvertToLowerCase(std::string);
    const std::map <char, char> UppercaseConvert;  //remove const to compile


};

Converter::Converter() {
    //remove const to compile
    const UppercaseConvert = { { 'A','a' },{ 'B','b' },{ 'C','c' },{ 'D','d'},{ 'E','e' },{ 'F','f' },
    { 'G','g' },{ 'H','h' },{ 'I','i' },{ 'J','j' },{ 'K','k' },{ 'L','l' },
    { 'M','m' },{ 'N','n' },{ 'O','o' },{ 'P','p' },{ 'Q','q' },{ 'R','r' },
    { 'S','s' },{ 'T','t' },{ 'U','u' },{ 'V','v' },{ 'W','w' },{ 'X','x' },
    { 'Y','y' },{ 'Z','z' } };
} 

std::string Converter::ConvertToLowerCase(std::string word) {

    std::string ConvertedString;
    for (char character : word) {
        if (UppercaseConvert[character]) {
            ConvertedString.push_back(UppercaseConvert[character]);
        }
        else ConvertedString.push_back(character);
    }
    return ConvertedString;
}


int main() {
    Converter ThisConverter;

    std::cout << "Enter a word in Caps:";
    std::string word;
    std::getline(std::cin, word);
    word = ThisConverter.ConvertToLowerCase(word);
    std::cout << "\n Your converted word is : " << word << std::endl;
    return 0;
}
Wes
  • 63
  • 7
  • Please post real code. `const std:map` is a syntax error. `const UppercaseConvert =` is also a syntax error. Hard to say what you're doing wrong if you don't show exactly what you *are* doing. See [How to Ask](http://stackoverflow.com/help/mcve) – M.M Apr 28 '16 at 02:09
  • You're distracting yourself with irrelevant details. One more reason preparing a [minimal complete example](http://stackoverflow.com/help/mcve) is a good idea. – Beta Apr 28 '16 at 02:11
  • " since this should be static" - if it should be static then why didn't you make it static? – M.M Apr 28 '16 at 02:12
  • I fixed the std::map, I'll write an example but the code works. The important bit is that it will not compile if the map is typed with const. Give me a few and I'll turn this into one piece of code. – Wes Apr 28 '16 at 02:14
  • I've added a completed example at the bottom, but the question is the same and more of an academic "what do I not understand about const and map" vs. code that does not work... It's obvious that it does not work... but why doesn't it work? – Wes Apr 28 '16 at 02:38
  • @M.M - "if it should be static then why didn't you make it static" .. maybe that is what I am doing wrong... map cant take a const but takes a static instead? If that is true then I need to dig deeper to understand the difference between const and static. Sorry, only a 3 day old programmer. – Wes Apr 28 '16 at 02:44
  • In this context, `const` means "cannot be changed", and `static` means "one instance of it in total" (as opposed to "one instance per class instance"). They are unrelated terms, it makes no sense to talk about "the difference between const and static". – M.M Apr 28 '16 at 02:55

1 Answers1

2

const UppercaseConvert = is a syntax error. When you refer to a variable that already exists, you just use its name, UppercaseConvert here. You don't repeat some parts of its declaration or qualifiers.


Let's talk about the line :

UppercaseConvert = { { 'A','a' },{ 'B','b' },{ 'C','c' },{ 'D','d'},{ 'E','e' },{ 'F','f' },
{ 'G','g' },{ 'H','h' },{ 'I','i' },{ 'J','j' },{ 'K','k' },{ 'L','l' },
{ 'M','m' },{ 'N','n' },{ 'O','o' },{ 'P','p' },{ 'Q','q' },{ 'R','r' },
{ 'S','s' },{ 'T','t' },{ 'U','u' },{ 'V','v' },{ 'W','w' },{ 'X','x' },
{ 'Y','y' },{ 'Z','z' } };

This is called assignment. You are changing the value that UppercaseConvert already has, to be a different value.

So, it is not possible to make UppercaseConvert be const and also have this line. Because if it is const then you cannot change its value.

I guess that what you intended to do was to initialize UppercaseConvert. To initialize means to supply a value which the variable will hold upon its creation. The way you wrote it so far, the variable is initailized to be an empty map and you try to change the map later on to have entries in it. The constructor body runs after the member variables have finished being initialized.

Link to further reading about initialization for non-static members

In comments it seems you also want the map to be static. Probably a good idea. For a static member, you do not put anything in the constructor. This is because the constructor is used to construct instances of your class. But a static member is not associated with any particular instance. A static member means that there is one instance of that member in total.

The class definition should contain:

static const std::map<char, char> UppercaseConvert;

and then in the .cpp file where you implement this class, but outside of any function, you write the definition with initializer (and you do not repeat the word static here):

const std::map<char, char> BCLogic::UppercaseConvert =
{ { 'A','a' },{ 'B','b' },{ 'C','c' },{ 'D','d'},{ 'E','e' },{ 'F','f' },
{ 'G','g' },{ 'H','h' },{ 'I','i' },{ 'J','j' },{ 'K','k' },{ 'L','l' },
{ 'M','m' },{ 'N','n' },{ 'O','o' },{ 'P','p' },{ 'Q','q' },{ 'R','r' },
{ 'S','s' },{ 'T','t' },{ 'U','u' },{ 'V','v' },{ 'W','w' },{ 'X','x' },
{ 'Y','y' },{ 'Z','z' } };

Important note: Even though this line contains the = symbol, it is not an assignment. This is a declaration. The difference between assignment and declaration is that in assignment you refer to a variable that already exists; in a declaration you are creating a variable as evinced by the type specifiers. In fact you can (and probalby should) omit the = from this line. But I included it to make this point as you will see people using = here.


As noted in comments, you will also need to change the line UppercaseConvert[character]. The map::operator[] can only be used on non-const maps because part of its behaviour is to add a new entry if the character did not already exist in the map.

The loop could be:

for (char character : word)
{
    auto it = UppercaseConvert.find(character);
    char ch = it == UppercaseConvert.end() ? character : it->second;
    ConvertedString.push_back( ch );
}

If you also plan to look the map up in other places then it'd be a good idea to separate that lookup code into its own function.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • 1
    Maybe you should say that if it wasn't supposed to be static you could initialize it with the constructor on a per class bases using the constructor's initializer list. And either way the [] operator doesn't work on a const map - you need to call the at() function. – Jerry Jeremiah Apr 28 '16 at 03:16
  • I think I'm getting this. The reason I added const in both places is because that's what was said in the class (which as with any class it is oversimplified). So I have methods that are declared with const ie: – Wes Apr 28 '16 at 04:08
  • I think I'm getting this. The reason I added const in both places is because that's what was said in the class (which as with any class it is oversimplified). So I have class methods that are declared with const ie: bool GetSomeValue() const; and then defined bool class::GetSomeValue() const{}; So while I understand mostly how to use it with map, very fuzzy on the difference. Lastly, can you tell me how this line reads: char ch = it == UppercaseConvert.end() ? character : it->second; I've never seen this so not sure how to interpret it. – Wes Apr 28 '16 at 04:13
  • function declarations are completely different to assigning to variables – M.M Apr 28 '16 at 04:14
  • Do you have any recommendations on literature that really digs down and explains these different types of declarations (const, static, constexpr...etc and how to properly use them? I have looked at this page for the use of const and will keep reading it till I digest it: http://duramecho.com/ComputerInformation/WhyHowCppConst.html – Wes Apr 28 '16 at 04:26
  • 1
    [See here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – M.M Apr 28 '16 at 04:27