5
votes
int main()
{
 const int a = 1;
 const int b = 2;
 typedef decltype(a*b) multiply_type;
 cout << typeid(multiply_type).name() << endl;
 return 0;
}

The return value of the program is that multiply_type is int. I'm quite surprised. I expected the type deduction to yield const int and since the expression yields a pr value, the resultant type would be const int.

PS: With auto the return value would be int as it drops the const qualifier.

Any ideas why multiply_type is int instead of const int with decltype ?

Edit: Added an addition example which is also related to cv-qualifier.

#include<iostream>
#include<typeinfo>


using namespace std;

struct Details
{
    int m_age;
};

int main()
{
 const Details* detail = new Details();
 typedef decltype((detail->m_age)) age_type;
 cout << typeid(age_type).name() << endl;

 int a = 1;
 age_type age = a;
 age = 10; // This is not possible. Read only. 
 cout << typeid(age).name() << endl; // This returns the type as int though. Then why is 20 not possble ?
 return 0;

}

Edit 2: Check our the link. http://thbecker.net/articles/auto_and_decltype/section_07.html `

int x;
const int& crx = x;
/ The type of (cx) is const int. Since (cx) is an lvalue,
// decltype adds a reference to that: cx_with_parens_type
// is const int&.
typedef decltype((cx)) cx_with_parens_type;` 
1
Value categories and cv-qualifiers are independent things. In your particular case, [expr]/6 applies; there are no prvalues of const scalar type. - Columbo
See my edit. I meant to say, the expression is a pr-value. - KodeWarrior
I have no idea how that's related to my answer. - Columbo
@KodeWarrior Because I have never encountered a language rule that says that constness of return value of an operation depends on constness of the arguments (at least for in-built arithmetic operators. You can achieve it for custom types with overloading, though). And because it would achieve nothing useful. - eerorika
Btw., age_type is const int&, not int. The string produced by typeid is not really expressive. - Columbo

1 Answers

1
votes

decltype evaluate it argument as it is, decltype(i) where i is cv-qualified lvalue, results in declaring type cv-qualified, but the expression of i*i in decltype(i*i) create a non materialized prvalue with type of i with non cv-qualified, prvalue don't have an explicit notion of constness. your code produce the same as:

using T = const int;
static_assert(is_same<int, decltype(0)>(), "Failed");

The fact that typeid is not showing the cv-qualification is because they a ignored:

5.2.8.5 - If the type of the expression or type-id is a cv-qualified type, the result of the typeid expression refers to a std::type_info object representing the cv-unqualified type.