Как использовать cv-квалификатор для метода, который возвращает ссылку на массив?

Если у меня есть функция-член, которая возвращает ссылку на массив (qaru.site/info/198688/...), как я могу добавить спецификатор const к функции? Этот код не компилируется в Visual С++ 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;
    }
};

Ответ 1

const int (&f2() const )[10]
{
    return data;
}

Ответ 2

Я предлагаю несколько решений, которые, на мой взгляд, более читабельны, чем прямой ответ на этот вопрос. Я уверен, что есть энтузиасты C-грамматики, и я извиняюсь перед ними за то, что у меня ужасная память, и я не могу запомнить эти правила C.

Тип псевдонима

Вы можете избежать странной грамматики на основе C, используя псевдоним типа:

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

Live demo

или с typedef (для С++ 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

Авто

С С++ 14 вы также можете использовать возвращаемые типы auto:

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

Live demo

Стандартный массив

С С++ 11 вы также можете просто использовать 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

и упростите его:

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

Live demo

который несколько функционально эквивалентен, но легче на глазах.

Ответ 3

Используйте typedef. Это облегчит всем жизнь:

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

    Data const& f1()
    {
        return data;
    }

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

То же самое можно сделать с помощью std::array<int, 10>:

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

что является еще одним преимуществом std::array по необработанному массиву.

Ответ 4

Ну, typedef может решить вашу проблему и сделать ее более читаемой:

struct A
{
    typedef int array_t[10];

    ...

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