简体   繁体   中英

Why does this compiler warning only show for int but not for string? "type qualifiers ignored on function return type"

I am a bit confused about some warnings I get when compiling my C++11 code using mingw64. This is my MWE:

class A{
    const string name;
    const int ID;

    public:
        A(string name_, int ID_) : name(name_), ID(ID_){
            // initialize non-const members
        }
        const string getName() const{return name;}
        const int getID() const{return ID;}
};

int main()
{   
    A aObj = A("Aname", 1);
    std::cout << "getName() = " << aObj.getName() << std::endl;
    std::cout << "getID() = " << to_string(aObj.getID()) << std::endl;
}

Code executes fine and does what it should, but I get this compiler warning:

,,localtest.cpp:10:9: warning: type qualifiers ignored on function return type

[-Wignored-qualifiers] const int getID() const{return ID;}

So the warning only shows for getID() but not for getName() , even though both have the same type qualifiers. Can somebody explain to me, why this warning seems only to show for string but not for int ? I suppose it has something to do with int being a primitive data type - but what exactly?

std::string is a class that has member functions that can be constant. If you have a constant object of the class you may apply only constant member functions.

As for fundamental types like for example int then the qualifier const does not make a sense for a return value because in any case you can not change the returned value.

Here is a demonstrative program

#include <iostream>
#include <string>

template <typename T>
const T f( const T &t )
{
    return t;
}

int main() 
{
    std::cout << f( std::string( "Hello World!" ) ).length() <<  '\n';

//  Invalid assignment  
//  f( 10 ) = 20;
    
    return 0;
}

The program output is

12

As you can see you can apply constant member functions to the returned object of the type std::string (but you can not apply non-constant member functions). And you can not change the returned value of the type int .

Consider the following:

struct MyType {
  void foo() const;
  void bar();
};

MyType getMutable();
const MyType getConst();

int main() {
  getMutable().foo(); // fine
  getMutable().bar(); // fine
  getConst().foo(); // fine
  getConst().bar(); // Not allowed!
}

There just isn't anything equivalent for int . The set of operations you can do on a int RValue is the exact same as for a const int RValue. That's why you are getting a redundancy warning.

See [expr.type] :

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

The essence is: you can have expressions of const class or array types, but not of const primitive types.

Since int is not a class, it is enough for return type to be rvalue to prevent any and all modifications of the returned object. Thus,

getInt(20) = 500;

would not be compilable code, and there are no members you could invoke on objects of int type. This is why const-qualifying built-in types as return values make no sense, and compiler is warning you about that.

But the situation is different for the classes.

getString("string").clear();

Might be either valid or invalid code, based on whether getString returns non-const or const std::string object, thus compiler is not issuing a warning in the latter case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM