11

If I have a member function which returns a reference to an array (https://stackoverflow.com/a/5399014/4304120), how can I add a const qualifier to the function? This code doesn't compile under Visual C++ 2010.

struct A
{
    int data[10];

    // this compiles
    const int (&f1())[10]
    {
        return data;
    }

    // error C2143: syntax error : missing ';' before '<cv-qualifer>'
    const int (&f2())[10] const
    {
        return data;
    }
};
Community
  • 1
  • 1
Marian Spanik
  • 1,079
  • 1
  • 12
  • 18
  • 1
    Since C++14 you can avoid the problem with `const auto& f2() const { return data; }` – M.M May 25 '16 at 13:30

4 Answers4

22

I'll propose few solutions which are in my opinion more readable than the extremely direct answer to this question. I'm sure there are C grammar enthusiasts out there and I apologize to them for I have terrible memory and I'm not able to remember those C rules.

Type alias

You can avoid the weird C-based grammar by using a type alias:

struct A {
    using data_type = int[10];
    data_type data;
    data_type& f1() { return data; }
    data_type const& f2() const { return data; }
};

Live demo

or with typedef (for before C++11):

struct A {
    typedef int data_type[10];
    data_type data;
    data_type& f1() { return data; }
    data_type const& f2() const { return data; }
};

Live demo

Auto

Since C++14 you can also use auto return types:

struct A {
    int data[10];
    auto& f1() { return data; }
    auto const& f2() const { return data; }
};

Live demo

Standard array

As of C++11 you can also just use std::array:

struct A {
    using data_type = std::array<int, 10>;
    data_type data;
    data_type& f1() { return data; }
    data_type const& f2() const { return data; }
};

Live demo

and simplify it to:

struct A {
    std::array<int, 10> data;
};

Live demo

which is somewhat functionally equivalent but easier on the eyes.

Community
  • 1
  • 1
Shoe
  • 74,840
  • 36
  • 166
  • 272
17
const int (&f2() const )[10]
{
    return data;
}
101010
  • 41,839
  • 11
  • 94
  • 168
6

Use a typedef. It'll make everybody's life easier:

struct A
{
    using Data = int[10];
    Data data;

    Data const& f1()
    {
        return data;
    }

    Data const& f2() const
    {
        return data;
    }
};

The same could be accomplished with std::array<int, 10>:

std::array<int, 10> data;
std::array<int, 10> const& f2() const { return data; }

which is another advantage of std::array over raw array.

Barry
  • 286,269
  • 29
  • 621
  • 977
4

Well a typedef could solve your problem, and make it a little more readable:

struct A
{
    typedef int array_t[10];

    ...

    const array_t& f2() const
    {
        return data;
    }
};
Smeeheey
  • 9,906
  • 23
  • 39
  • I am sorry, I spelled the question incorrectly. I want to add the qualifier to the function, not the return value. – Marian Spanik May 25 '16 at 13:27
  • It's teh same thing though. You can use the `typedef` and then add `const` after the function like usual – coyotte508 May 25 '16 at 13:28
  • 1
    Yes, exactly. Edit made – Smeeheey May 25 '16 at 13:38
  • 1
    Using C `typedef` kinda just exchanges one readability problem for another, due to the element and alias types being the wrong way around conceptually and versus all other uses. Using C++ `using` is superior. In fact, this might be a 'textbook' example of why the latter was added to C++. – underscore_d May 25 '16 at 22:21
  • @underscore_d what do you mean? Typedef is same way around as variables being defined. So what *other uses* did you mean? – JDługosz May 26 '16 at 04:01
  • 1
    @JDługosz I think what _underscore_d_ means here is that `typedef` can be seen as inconsistent when used for array/function declarations - `typedef int myType` vs. `typedef int arrayType[10]` - one would probably expect `typedef int[10] arrayType` (I realize there are rules for this and that according to them this does make sense, but I think this is what underscore_d meant). With a `using` directive, it is indeed more intuitive: `using arrayType = int[10];`. – user4520 May 26 '16 at 07:19
  • @szczurcio Exactly. Thanks! – underscore_d May 26 '16 at 12:34
  • But that's exactly the *same* (way around) as `int array_variable [10]`, so what does *all other uses* refer to? I don't know what *element and alias types* mean in this sentence. – JDługosz May 26 '16 at 19:35