Использование auto в качестве возвращаемого типа и возвращаемого значения nullptr в некоторых случаях - PullRequest
0 голосов
/ 06 июля 2019

Если у нас есть метод с типом возврата auto, но в метод мы вернем новый объект или nullptr. Если я правильно понимаю, когда мы вернем nullptr, он создаст и новый объект через конструктор.

Метод With.

Вопрос следующий: Какой тип будет использоваться вместо auto? Это будет зависеть от типа, возвращаемого на maybe или нет: maybe - это функция, которая возвращает Maybe<T>. Когда мы вызываем сначала With, возвращаемый тип - Maybe< Adress >; второй шаг это может быть Maybe< Adress >, так как это тип объекта или Maybe< std::string > - он возвращается, если контекст не nullptr.

struct Address {
    string* house_name = nullptr;
};

struct Person {
    Address* address = nullptr;
};

template <typename T> struct Maybe;

template <typename T> Maybe<T> maybe(T* context)
{
   return Maybe<T>(context);
}

template <typename T>
struct Maybe {
    T* context;

    Maybe(T *context) : context(context) { }

    template <typename TFunc>
    auto With(TFunc evaluator)
    { 
        return context != nullptr ? maybe(evaluator(context)) : nullptr;
    }
 };

 ...

 void print_house_name(Person* p)
 {
    auto z = maybe(p)
    .With([](auto x) { return x->address; })
    .With([](auto x) { return x->house_name; })
    .Do([](auto x) { cout << *x << endl; });
 }


int main()
{
   //print_house_name(nullptr);

   Person p;

   print_house_name(&p); // nothing

}

Ответы [ 2 ]

2 голосов
/ 06 июля 2019

Какой тип будет использоваться вместо auto?

Тип возврата вашей функции определяется типом выражения в единственном операторе return.В вашем случае это утверждение:

return context != nullptr ? maybe(evaluator(context)) : nullptr;

Возвращаемое выражение является троичным оператором, два потенциальных значения которого имеют разные типы (Maybe<C>, для некоторого класса C необязательно T и nullptr_t).Это правильно, только если один из типов неявно конвертируется в другой.Обычно nullptr_t преобразует только в / из других типов указателей, поэтому давайте посмотрим на неявные преобразования, определенные для Maybe (есть только один):

Maybe(T *context) : context(context) { }

Тип указателя может быть преобразован в Maybe.Таким образом, nullptr преобразуется в C*, который затем преобразуется в Maybe<C> объект (контекст которого равен нулю).Опять же, я использую C вместо T, потому что этот тип не обязательно должен быть тем же параметром шаблона, который является частью типа *this.Возвращаемый тип является одинаковым независимо от значения context.

Если вы хотите увидеть этот неявный разрыв преобразования, сделайте преобразование в Maybe явное, как в explicit Maybe(T *context) : context(context) { }.

0 голосов
/ 06 июля 2019

auto не волшебно. Это просто заполнитель, который ваш компилятор заполняет конкретным, выводимым типом. Конечный результат точно такой же , как если бы вы написали выведенный тип вручную.

«Если я правильно понимаю, когда мы возвращаем nullptr, он также создаст новый объект через конструктор». Нет. Возвращение nullptr не вызывает никаких конструкторов. Он просто возвращает нулевое значение соответствующего типа. Ни один объект не построен.

«Какой тип будет вместо auto» - возвращаемым типом будет любой тип того, что вы на самом деле возвращаете равно . И это может быть только один определенный тип.

...