эквивалент std :: tuple второго члена std :: pair? - PullRequest
0 голосов
/ 28 ноября 2018

Я конвертирую эту функцию, чтобы использовать std::tuple, который не имеет first и second таких членов, как std:pair.

std::type_index argumentType(const std::string& name) const
{
    return std::find_if(args_.begin(), args_.end(),
        [&name](std::pair<std::string, std::type_index> arg)->bool
        {
            return arg.first == name;
        }
    )->second;
}

Меня смущает синтаксис ->secondчто это делает?и эквивалентен std::get<1>(arg)

std::type_index argType(const std::string& name) const
{
    return std::find_if(args_.begin(), args_.end(),
        [&name](std::tuple<std::string, std::type_index, Attribute> arg)->bool
        {
            return std::get<0>(arg) == name;
        }
    )std::get<1>(arg);

Пример 2:

std :: pair

bool hasArg(const std::string& name) const
{
    return std::find_if(args_.begin(), args_.end(),
        [&name](std::pair<std::string, std::type_index> arg)->bool
        {
            return arg.first == name;
        }
    ) != args_.end();
}

std :: tuple

bool hasArg(const std::string& name) const
{
    return std::get<0>(*std::find_if(args_.begin(), args_.end(),
        [&name](std::tuple<std::string, std::type_index, Attribute> arg)->bool
        {
            return std::get<0>(arg) == name;
        }
    )) != args_.end();
}

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Оформление документации std :: find_if

Так что std::find_if вернет итератор.В коде # 1 было итератор для сопряжения, поэтому ->second будет обрабатывать second элемент std :: pair .Вы используете -> перегруженный оператор для итератора .

Пример:

auto it = std::find_if(args_.begin(), args_.end(),...);
if(it != args_.end()) // This is important to NOT dereference iterator if it is pointing to end
{
    // also you can write (*it).second; (first use dereference operator)
    return it->second;
}
// ...

Так что в вашем случае вам следует изменить его на:

std::type_index argType(const std::string& name) const
{
    // Please don't do so much in 1 line. Compiler will optimize this for you :)
    // Please check for std::end, this is potential dangerous.
    return std::get<1>(*std::find_if(args_.begin(), args_.end(),
        [&name](std::tuple<std::string, std::type_index, Attribute> arg)->bool
        {
            return std::get<0>(arg) == name;
        }
    ));
}

Тот же пример:

auto it = std::find_if(args_.begin(), args_.end(),...);
if(it != args_.end()) // This is important to NOT dereference iterator if it is pointing to end
{
    return std::get<1>(*it);
}
// ...

Важно

Пожалуйста, рассмотрите также случай, когда вы не нашли свой элемент.std::find_if вернет std::end(args_), если элемент, который вы ищете, не существует.Поэтому вызов ->second или std::get<1>(*it) является неопределенным поведением и может разрушить.


Исправлено для функции hasArg.Теперь вам не нужно разыменовывать свой итератор.

bool hasArg(const std::string& name) const
{
    return std::find_if(std::begin(args_), std::end(args_),
        [&name](const std::tuple<std::string, std::type_index, Attribute>& arg)->bool
        {
            return std::get<0>(arg) == name;
        }
    ) != std::end(args_);
}

В этом решении я использовал std :: begin и std :: end .Это более универсальный способ вместо вызова arg_.begin():)

Пожалуйста, проверьте, как я определил синтаксис вашего второго примера.И последнее: когда вы используете std::find_if и лямбду, чтобы найти то, что вы ищете, аргумент должен быть const& в большинстве случаев :), потому что мы не хотим делать здесь копию.

0 голосов
/ 28 ноября 2018

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

Да, std::get<1> для кортежа будет примерно таким же, но синтаксис будет другим:

auto it = std::find_if(...);
return std::get<1>(*it);

Вам нужно использовать оператор разыменования * вместо оператора стрелки, потому что std::get - это свободная функция, а не член кортежа.

...