Как сократить подпись этого метода?

У меня есть следующий класс с подписью метода, как показано ниже:

class Foo
{
    public:
        std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}

В файле реализации у меня есть следующее:

std::vector<std::string> Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

Итак, я подумал про себя, давайте посмотрим, смогу ли я немного упростить эту сигнатуру функции с помощью некоторой автоматической магии, поскольку она становится "немного заполненной строкой"! Итак, я попробовал это ...

class Foo
{
    public:
        auto barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}

auto Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

Теперь, игнорируя тот факт, что да, я могу использовать «using namespace std», чтобы сильно его урезать, мне было интересно, почему компилятор выдал мне ошибку "функция, которая возвращает 'auto', не может использоваться до того, как она будет определена".

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

class Foo
{
    public:
        std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&) -> std::vector<std::string>;
}

Но тогда, если вы воспользуетесь описанным выше, это будет не лучше, чем было раньше. Итак, помимо «использования пространства имен std», есть ли лучший способ сделать это, и почему компилятор не может определить возвращаемый тип в этом случае? Или даже, зависит ли это от того, как вызывается этот метод, из-за чего компилятор не может определить возвращаемый тип.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
124
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема здесь в том, как работают включаемые файлы. Ваша ошибка:

a function that returns 'auto' cannot be used before it is defined

означает, что в файле вы используете свою функцию, ее определение (то есть реализация) не было нигде в файле до использования. Это означает, что компилятор, компилирующий ваш код с использованием функции, не может определить тип возвращаемого значения функции, поскольку для этого требуется доступ к определению (реализации). Наиболее вероятная причина этого в том, что определение (реализация) функции находится в ее собственном исходном файле (.cpp, .c и т. д.), Который не включен. Чтобы более полно понять это, я рекомендую прочитать ответ это и, возможно, ответ это.


Чтобы ответить на главный вопрос, вероятно, самый простой способ сократить эту подпись - использовать typedef. В частности, вы можете добавить следующий код везде, где считаете нужным, при условии, что область видимости подходит (я бы добавил его как публичный член в вашем классе):

typedef std::vector<std::string> strvec;

Это позволяет вам переписать подпись вашего метода как более управляемую:

strvec barreuslts(const strvec&, const strvec&)

Как я уже сказал выше, использование typedef или using было тем, что я уже рассматривал, и я действительно хотел только немного сократить длину строки, не меняя всю подпись. Однако я еще не подумал о другом, о чем вы отметили. Поскольку я включаю только заголовок и эту реализацию, необходимую для вывода типа, это причина, по которой я получил ошибку. Хороший.

The Welder 15.08.2018 13:42

Придерживаясь C++ 11, вы не можете полагаться на выведенные типы возвращаемого значения, вам нужен конечный тип возвращаемого значения (хотя C++ 14 допускает это). Поскольку в вашем случае нет ничего особенного в завершающем возвращаемом типе, т.е. никакое выражение не передается decltype для определения возвращаемого типа, я бы вместо этого попытался сократить сигнатуру метода с помощью некоторых псевдонимов типов:

class Foo
{
    public:
        using StrVec = std::vector<std::string>;

        StrVec barResults(const StrVec&, const StrVec&);
};

Foo::StrVec Foo::barResults(const StrVec& list1, const StrVec& list2)
{
    StrVec results;
    // small amount of implementation here...
    return results;
}

Это идея, о которой я уже думал, но этот код был для некоторых младших программистов и не хотел слишком усложнять вещи, используя что-то вроде typedef или using. Конечно, это хороший подход.

The Welder 15.08.2018 13:39

Я сомневаюсь, что введение автоматического возврата уменьшит сложность, в то время как использование определения типа в классе с разумным именем может сделать код более читаемым. Кстати, я бы использовал объявление C++ 11 -> StrVec синтаксиса конечного возвращаемого типа, чтобы избавиться от надоедливого Foo :: в начале, хотя в конце это стоит 2 дополнительных символа для Foo!

Gem Taylor 15.08.2018 17:35

Если вы просто ищете визуально привлекательный способ работы с более длинными подписями, перестаньте заставлять все располагаться в одной строке. Будьте либеральны с вертикальным интервалом и вставляйте разрывы строк. Подпись содержит качественную информацию для вызывающего абонента, и вы, возможно, ищете многострочную подпись. Если вы работаете с шириной страницы 80 символов, пересмотрите отступ в спецификаторе доступа.

class Foo
{
public:
    std::vector<std::string> barResults(const std::vector<std::string>&,
                                        const std::vector<std::string>&);
}


std::vector<std::string>
Foo::barResults(const std::vector<std::string>& list1,
                const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

Когда дело доходит до разделения объявления, существует множество стилей. Наличие такого инструмента, как clang-format в вашем наборе инструментов, сделает это автоматически и последовательно за вас.

Обычно я либерально отношусь к пробелам, но это скорее сложный вопрос как о форматировании, так и о том, что вызвало ошибку. Я также НЕТ поклонник использования auto везде, как и вы, я согласен с тем, что подпись содержит информацию о качестве. Просто в этом случае подпись была довольно многословной, и когда я хотел ее немного укоротить, с небольшим использованием auto, возникла ошибка, которой я не ожидал. Теперь, когда кто-то указал на это, становится понятным, почему это произошло.

The Welder 15.08.2018 13:46

Другие вопросы по теме