5

Please consider the code below, in particular, observing that get_length returns const size_t.

#include <stdio.h>

const size_t get_length(void)
{
    return 123;
}

void foo(void)
{
    size_t length = get_length();
    length++;
    
    printf("Length #1 is %zu\n", length);
}

void bar(void)
{
    // Still 123 because length was copied from get_length
    // (copy ellision notwithstanding, which is not the point here)
    size_t length = get_length();
    
    printf("Length #2 is %zu\n", length);
}

int main(void) {
    foo();
    bar();
}

Output:

Length #1 is 124
Length #2 is 123

I am getting the following warning from clang-tidy:

Clang-Tidy: Return type 'const size_t' (aka 'const unsigned long')
is 'const'-qualified at the top level,
which may reduce code readability without improving const correctness

This message has two parts about the return type:

  • Const correctness is not improved
  • Code readibility is reduced

I understand the first part where, like in foo and bar, as the callers are not required to specify their local variables as const, ultimately const correctness is not improved, i.e. there is nothing preventing the callers from ignoring the fact that the callee returns a const object.

But I am not sure what is meant by "code readability is reduced" - is that simply because it may give some people false expectations that the return type shall never be modified? Or is there something else to it that only starts to make sense with more complex return types?

I ask because I do not consider readability to be reduced here and I am just not sure what the intention could have been behind the warning. Thanks.

  • 1
    what is the reason for using `const` here? if there is none, then that affects readability. – jdigital Sep 19 '20 at 18:28
  • @jdigital How in terms of the C language am I to explain to you what the reason of using "const" is? I.e. it already says "const". What else can I tell you about it, using the C language? –  Sep 19 '20 at 18:29
  • i'm asking why you chose to use `const` here. you could have omitted it. – jdigital Sep 19 '20 at 18:32
  • This is not the point. I chose "const" because it is part of the language and I am trying to understand this particular message from clang-tidy. The code is to serve as an illustration. –  Sep 19 '20 at 18:36
  • 1
    @Terry You are allowed to use `const` there, but Clang-Tidy is also correct in flagging it as ineffective. See the related [Should useless type qualifiers on return types be used, for clarity?](https://stackoverflow.com/questions/1579435/should-useless-type-qualifiers-on-return-types-be-used-for-clarity), [Benefits of using “const” with scalar type?](https://stackoverflow.com/questions/8406898/benefits-of-using-const-with-scalar-type-e-g-const-double-or-const-int). – dxiv Sep 19 '20 at 18:41
  • @dxiv I like the term "ineffective", this makes sense. It looks that this is essentially a duplicate question and if you turned your comment into an answer, I would be happy to accept it. –  Sep 19 '20 at 18:59

2 Answers2

5

You are allowed to use const there, but Clang-Tidy is also correct in flagging it as ineffective.

The related Q&As under Should useless type qualifiers on return types be used, for clarity?, Benefits of using “const” with scalar type? cover the part of why const is ineffective in this context.

The other part of the question about why "code readability is reduced", that's because a superfluous const qualifier can potentially distract from the core fact that const'ness is not carried over value assignments. It could, for example, tempt the client code into mistakenly believing that the return value must be used a const as well e.g. const size_t val = get_length(); which is not true, as the posted code shows.

A similar caveat goes for arguments. Suppose the return value of const size_t get_length(); is always passed to another function baz(get_length());. The argument of baz needs not (and arguably should not) be declared as const size_t but just plain size_t i.e. void baz(size_t);.

dxiv
  • 16,984
  • 2
  • 27
  • 49
2

1. Const correctness is not improved

The returned value can only be used as a rvalue. There is no possibility to change a rvalue, so const correctness is already given.

2. Code readability is reduced

You are leading the reader into false assumptions.

Examples

/* the rest of your example... */

void baz(void)
{
    size_t length = get_length();
    length += 42;
    
    printf("Length #2 is %zu\n", length);
}

There is nothing to prevent the change of length. It gets initialized by a constant, right, like size_t length = 123;

/* the rest of your example... */

void fu(void)
{
    const size_t length = get_length();
    length += 42; /* will give a compile-time error */
    
    printf("Length #2 is %zu\n", length);
}
the busybee
  • 10,755
  • 3
  • 13
  • 30
  • 1
    Thanks for the answer - in the end I chose the other one because it was somewhat easier for me to understand but yours is a good one too! –  Sep 19 '20 at 20:02