Logo

Blog


Exploring the impact of top-level cv-qualifiers on type-deduction

In today's post, I will continue where I left off with last month's post Understanding the role of cv-qualifiers in function parameters. This time, I will focus on type deduction.

auto type deduction

Based on the initial code from C++ top-level qualifiers explained, I create the following new variables by using auto:

1
2
3
4
5
auto arobert  = robert;   F 
auto aamy     = amy;      G 
auto aalfred  = alfred;   H 
auto alinda   = linda;    I 
auto amelissa = melissa;  J 

As a reminder, here is the code from the initial post:

1
2
3
4
5
char              robert{};   A 
const char        amy{};      B 
const char*       alfred{};   C 
char* const       linda{};    D 
const char* const melissa{};  E 

With your existing knowledge, my question is, what are the resulting types for these five new variables?

As so often, C++ Insights is at your service: cppinsights.io/s/32e26696.

1
2
3
4
5
char        arobert  = robert;
char        aamy     = amy;
const char* aalfred  = alfred;
char*       alinda   = linda;
const char* amelissa = melissa;

When it comes to type-deduction, as for parameters, the compiler omits top-level qualifiers. Type deduction is all about the type. On that note, char& results in char as & is a qualifier.

Of course, you can add top-level cv-qualifiers to the auto declaration to preserve the variable's original qualifiers.

What about templates?

Well, templates were first. auto is more or less an artifact of type deduction as it was required for templates.

Suppose you have a function template Fun

1
2
3
4
5
template<typename T>
void Fun(T arg)
{
  std::println("{}", std::is_const_v<T>);
}

and call Fun with the variables A and B:

1
2
3
Fun(robert);
Fun(amy);
Fun<const char>(amy);

what is the output of the program?

1
2
3
false
false
true

See for yourself compiler-explorer.com/z/7Y4shYET1. Only the last case prints true.

Using C++ Insights helps shedding some light on what's going on cppinsights.io/s/eca3e365.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
/* First instantiated from: insights.cpp:14 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void Fun<char>(char arg)
{
  std::println(std::basic_format_string<char, const bool &>("{}"), std::is_const_v<char>);
}
#endif


/* First instantiated from: insights.cpp:16 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void Fun<const char>(const char arg)
{
  std::println(std::basic_format_string<char, const bool &>("{}"), std::is_const_v<const char>);
}
#endif

You can see that there are two functions: - void Fun<char>(char arg) - void Fun<const char>(const char arg)

It looks like a top-level cv-qualifier can matter. But the effect only kicked in with my last call to Fun where I explicitly specified the type Fun<const char>(amy). Things are different for class templates. Templates and type-deduction are interesting lands.

Andreas