【问题标题】:Perfect forwarding of variadic template templates可变参数模板模板的完美转发
【发布时间】:2018-06-11 15:54:35
【问题描述】:

我目前正在使用一些新的 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 函数,那个函数只接受一个参数。有谁知道为什么会这样?如果您需要了解更多信息,请告诉我。

【问题讨论】:

  • 转发引用类似于T&amp;&amp;Op&lt;T&gt; 已经指定了值类别。

标签: c++ variadic-templates optional c++17 variadic-functions


【解决方案1】:

optional_min 的参数都不是转发引用。它们都是右值引用。

当您将参数声明为对推导的模板类型参数的右值引用时,会形成转发引用,但这里不是这种情况。 optional_min 的参数是对推导模板 template 参数实例化的右值引用。

为避免这种情况,只需去掉Opt0Opt1Opts模板模板参数,直接使用类型参数即可:

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

如果这是您的目标,您可以使用 SFINAE 将类型参数限制为 std::optional 的实例化。

【讨论】:

  • 谢谢!这非常有帮助。
  • 其实我有个问题...
  • 我删除了那个位。你是按价值返回的,所以我完全错了。
猜你喜欢
  • 2011-09-23
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多