Идеальная пересылка шаблонов - PullRequest
0 голосов
/ 11 июня 2018

В настоящее время я играю с некоторыми из новых функций C ++ 17, в частности std::optional, и я решил, что мне нужно придумать функцию поиска минимума с использованием шаблонов с переменными шаблонами.Это то, что у меня есть до сих пор:

template <template <typename> typename Opt, 
          typename T>
Opt<T> optional_min(Opt<T>&& opt) {
    return std::forward<Opt<T>>(opt);
}

template <template <typename> typename Opt0,
          template <typename> typename Opt1,
          template <typename> typename... Opts, typename T >
std::common_type_t<Opt0<T>, Opt1<T>, Opts<T>...> 
optional_min(Opt0<T>&& opt0, Opt1<T>&& opt1, Opts<T>&&... opts) {
    if (!opt0 && !opt1) 
    {
        return optional_min(std::optional<T>(std::nullopt), std::forward<Opts<T>>(opts)...);
    } 
    else if (opt0 && !opt1) 
    {
        return optional_min(opt0, std::forward<Opts<T>>(opts)...);
    } 
    else if (!opt0 && opt1) 
    {
        return optional_min(opt1, std::forward<Opts<T>>(opts)...);
    } 
    else 
    {
        return (*opt0 < *opt1) ? 
            optional_min(opt0, std::forward<Opts<T>>(opts)...) 
                : optional_min(opt1, std::forward<Opts<T>>(opts)...);
    }
}

int main() {
    std::optional<int> a = 9;
    std::optional<int> b = std::nullopt;
    std::optional<int> c = 4;

    if (auto x = optional_min(a, b, c)) 
        std::cout << *x << std::endl;

    return 0;
}

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

error: no matching function for call to 'optional_min(std::optional<int>&, std::optional<int>&, std::optional<int>&)'

error: cannot bind rvalue reference of type 'std::optional<int>&' to lvalue of type 'std::optional<int>'
  auto x = optional_min(a, b, c);

Мой компилятор также сообщает мне, что моя переменная optional_min функция является лишь близким совпадением, и что она пытается сопоставить мою другую функцию optional_min, этуэто принимает только один аргумент.Кто-нибудь знает, почему это может иметь место?Пожалуйста, дайте мне знать, если вам нужно узнать немного больше.

1 Ответ

0 голосов
/ 11 июня 2018

Ни один из параметров optional_min не является ссылкой для пересылки.Все они являются ссылками rvalue.

Пересылочные ссылки формируются, когда вы объявляете параметр как ссылку на rvalue на выводимый параметр типа шаблона, но здесь это не так.Параметры optional_min представляют собой rvalue ссылки на экземпляры выведенного шаблона template параметры.

Чтобы избежать этого, просто избавьтесь от шаблонов Opt0, Opt1 и Optsпараметры шаблона и непосредственное использование параметров типа:

template <typename Opt0, typename Opt1, typename... Opts>
auto optional_min(Opt0&& opt0, Opt1&& opt1, Opts&&... opts) {
    //...
}

Вы можете использовать SFINAE, чтобы ограничить параметры типа экземплярами std::optional, если это ваша цель.

...