Type of member variables in a const member function
Asked Answered
G

2

12

When I have a member function marked as const and inspect the types of the member variables I get some results I don't expect.

#include <iostream>
#include <string>

template<typename T>
struct type_printer;

class const_type_test {
public:
    void test() const {
        type_printer<decltype(value)> _;
    }
    int& test2() const {
        return value;
    }
    void test3() const {
        auto& x = value;
        type_printer<decltype(x)> _;
    }
    void test4() const {
        auto* x = &value;
        type_printer<decltype(*x)> _;
    }
private:
    int value;
};

int main(int argc, char** argv) 
{
    const const_type_test x;

    return 0;
}

My understanding is that when you are in a const method the method is effectively some name mangled name then they parameter type is classname const* const. I always thought that in the const method scope the member variables are effectively const, i.e. value would be const int. However when using the compiler error to deduce the types I get types I don't expect.

The error output for void const_type_test::test() const: aggregate type_printer<int> _ has incomplete type and cannot be defined, type_printer<decltype(value)> _;

So I am seeing the type was deduced as int. I thought it would be const int as you can not change the value. Am I using decltype wrong? Or have I a hole in my understanding.

The reason I guess for asking is that in test2 the compiler complains: binding reference of type int& to const int discards qualifiers. Which is exactly what I expect. Can bind a const reference to non const reference.

Example 3 shows the following error: error: aggregate type_printer<const int&> _ has incomplete type and cannot be defined type_printer<decltype(x)> _. Which is what I expect it has been deduced as a const reference.

Example 4: deduces also a type_printer<const int&> which I thought would be a pointer.

Keen to get some reference to the standard to find out where the holes in my knowledge are. I am also wondering if there are some weird type deduction rules when using decltype that are tripping me up.

Gaelic answered 10/6, 2020 at 13:30 Comment(0)
E
8

decltype has special rule for class members. It returns the actual type of the member. If you want decltype to consider the context (inside a const function), then you can wrap the expression inside parentheses.

Without Paranthesis:

 void test() const {
        type_printer<decltype(value)> _;
    }
c.cpp:10:39: error: implicit instantiation of undefined template 'type_printer<int>'
        type_printer<decltype(value)> _;

With Paranthesis:

 void test() const {
        type_printer<decltype((value))> _;
    }

c.cpp:10:41: error: implicit instantiation of undefined template 'type_printer<const int &>'
        type_printer<decltype((value))> _;

Reference:

https://en.cppreference.com/w/cpp/language/decltype

If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression. If there is no such entity, or if the argument names a set of overloaded functions, the program is ill-formed.

https://learn.microsoft.com/en-us/cpp/cpp/decltype-cpp?view=vs-2019

If the expression parameter is an identifier or a class member access, decltype(expression) is the type of the entity named by expression. If there is no such entity or the expression parameter names a set of overloaded functions, the compiler yields an error message.

Edelsten answered 17/6, 2020 at 7:47 Comment(3)
This special rule works for regular variables as well.Rand
@Rand out of curiosity, could you provide an example for a regular variable where the double parenthesis will yield a different result?Isometropia
@Isometropia Any variable that isn't an lvalue reference will give you a different result (decltype((var)) will always give you lvalue references, since all variables are lvalues.Rand
I
0

Make sure you are using the right type. Some types have lower ranges than others

Immiscible answered 23/6, 2020 at 21:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.