首页 > 解决方案 > 函数和类构造函数有什么区别?

问题描述

无法弄清楚下面的代码之间h1有什么区别:h2

#include <utility>

template <class Func>
struct Holder
{
    Holder(Func && func) : m_func(std::forward<Func>(func))
    {
    }

    Func m_func;
};

template <class Func>
auto MakeHolder(Func && func)
{
    return Holder<Func>(std::forward<Func>(func));
}

int main()
{
    auto func = [](int val) {};

    Holder h1 = MakeHolder(func);

    Holder<decltype(func)> h2(func);

    return 0;
}

为什么h1编译,但h2不编译?GCC的错误是

prog.cc:25 : 31 : error : cannot bind rvalue reference of type 'main()::<lambda(int)>&&' to lvalue of type 'main()::<lambda(int)>'
    25 | Holder<decltype(func)> h2(func);

Func函数模板参数中的decltype<func>类型是否main()不同?

标签: c++c++17

解决方案


不同之处在于 Holder 类是用不同的类型实例化的Func

  1. 对于h1,是main()::<lambda(int)>&
  2. 对于h2,是main()::<lambda(int)>

你看,当你有一个类型为 T 的变量并使用它时,使用的类型与变量的类型不同:T&而不是T. 但在decltype()语义上是不同的。

无论如何,您可以像这样编译代码:

#include <utility>

template <class Func>
struct Holder
{
    Holder(Func func) : m_func(func) { }

    Func m_func;
};

template <class Func>
auto MakeHolder(Func && func)
{
    return Holder<Func>(std::forward<Func>(func));
}

int main()
{
    auto func = [](int) {};
    [[maybe_unused]] Holder h1 = MakeHolder(func);
    [[maybe_unused]] Holder<decltype(func)> h2(func);
}

GodBolt

或者如果你真的必须 -std::move(func)在初始化列表中使用。但是 - 我不确定我是否会保留一个Func成员,因为它是任意Func的(例如,当它是一个引用或指向可能会消失的临时对象的指针时。


推荐阅读