从具有可变模板构造函数的类型构造一个 std::function 对象

constructing a std::function object from a type with a variadic template constructor

我有一个模板化的 class 实例化模板类型的内部对象,其构造函数将参数转发给内部对象。

template<typename T>
struct B
{
    template<typename... Args>
    B(Args&&... args) : m(std::forward<Args>(args)...) {}
    
    B(const B& b) = default;
    B(B&& b) noexcept = default;

    void operator()() { m(); }
    
    T m;
};

此外,此 class 是可调用的,它只是将调用委托给其内部成员。 它可调用的原因是因为我想将它作为 std::function 传递。 问题是编译器不允许我用 B 类型的对象初始化 std::function:

struct A
{
    void operator()() { std::cout << "A()\n"; }
};

void foo()
{
    B<A> b;
    std::function<void()> fb = b; //Error
}

错误是一个神秘的错误:

error: no matching function for call to ‘A::A(B&)’
     B(Args&&... args) : a(std::forward<Args>(args)...) {}

我的代码中没有任何地方调用过 A::A(B&)。 我希望 std::function 调用 B::B(B&) 构造函数将数据从 b 复制到 fb.

请注意,这只是因为 B 的可变模板构造函数而发生的。 以下代码编译正常:

A a;
std::function<void()> fa = a;

实例

template<typename... Args>
B(Args&&... args)

with Args... == B& 比复制或移动构造函数更适合复制 non-const 左值 B。实例化就像

B(B& args) : m(args) {}

它使用 A::A(B&)

您可以添加一个重载 B(B&) = default;,或者将一些 SFINAE 添加到您的模板构造函数中。