допустимо ли для автоматической переменной в функции представлять другой тип в различных вызовах? - PullRequest
0 голосов
/ 24 марта 2020

Рассмотрим следующую функцию:

using iteratorPair = std::pair<std::set<Record>::const_iterator, std::set<Record>::const_iterator>;
using iteratorList = std::vector<iteratorPair>;

template<class FunctionPtr>
iteratorList splitByParameter(iteratorPair& range, const FunctionPtr& accesorFunction)
{
    iteratorList list;

    list.push_back(range);

    auto firstValueFunction = std::bind(accesorFunction, *range.first);
    auto value = firstValueFunction();

    for (auto iterator = range.first; iterator != range.second; ++iterator)
    {
        auto iteratorValueFunction = std::bind(accesorFunction, *iterator);
        if (iteratorValueFunction() != value)
        {
            value = iteratorValueFunction();
            list.back().second = iterator;
            list.emplace_back(iterator, range.second);
        }
    }

    return list;
}

Его целью является создание диапазонов итераторов для записей в std::set, которые имеют общее значение ... например, всех людей с зелеными глазами, а затем могут быть вызывается снова для этих подмножеств для получения дополнительных диапазонов, например, для всех зеленоглазых мужчин. Вы передаете ему диапазон для работы и указатель на функцию доступа, которая возвращает значение, которое вы хотите сравнить.

Я построил это с MSV C 2019 16.4.3, и был удивлен, что смог Передайте accessorFunction указатели, которые имели различных типов возврата , чтобы в одном вызове функции value мог быть enum class, а в следующем вызове это мог быть double. Я использую различные сильные типы ( юниты ), которые не неявно конвертируются друг в друга.

Это имело бы смысл для меня, если бы value был тип шаблона, но я не думаю, что auto можно использовать таким образом? Это просто какая-то хитрость UB или компилятора, или это действительно допустимо использовать auto таким образом?

1 Ответ

2 голосов
/ 24 марта 2020

auto более или менее работает как вывод аргумента шаблона. Если вы вызываете шаблон функции с одним аргументом, который является типом, который зависит от параметра шаблона вашего шаблона, то точный тип этого шаблона функции будет определен во время создания вашего шаблона.

Так работает std::bind; результирующий тип такого вызова будет зависеть от типа аргументов шаблона, предоставляемых функции.

То же самое относится и к auto. Если выражение, тип которого выводится, зависит от одного из параметров вашего шаблона, тогда тип вывода будет основан на этой зависимости. И, таким образом, сам вычет придется отложить до времени создания экземпляра.

...