使用可变参数模板构造函数从类型构造std :: function对象

问题描述

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

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;
};

该类也是可调用的,它只是将调用委派给其内部成员。 它可调用的原因是因为我想将其作为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;

解决方法

的实例

<style scoped>
.time-slot-x-small {
  border-radius: 8px;
  font-size: 10px;
  height: 16px;
  background: #e0e0e0;
  padding: 1px 3px 1px 5px;
  margin: 2px 2px 0px 0px;
  color: black;
}
table {
  width: 100%;
  border-collapse: collapse;
}

table,th,td {
  border: 1px solid lightgray;
}
与复制或移动构造函数相比,带template<typename... Args> B(Args&&... args)

与复制非常量左值Args... == B&的匹配更好。实例化

B

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

您可以添加重载A::A(B&),也可以在模板构造函数中添加一些SFINAE。