函数和类构造函数有什么区别?

时间:2020-10-03 21:43:15

标签: c++ c++17

在下面的代码中无法找出h1h2之间的区别:

#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()类型不同吗?

1 个答案:

答案 0 :(得分:0)

区别在于,Func的Holder类是用不同的类型实例化的:

  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(例如,当它是对可能消失的临时内容的引用或指针时。

相关问题